text:
/*
 * @file cache-mgr.cpp
 * @brief implementation of Cache Manager
 *
 *  Created on: Oct 3, 2014
 *      Author: elenav
 */

/**
 * @namespace impala
 */
#include <string.h>
#include <boost/lexical_cast.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index_container.hpp>
#include "cache-mgr.hpp"

namespace impala {

#define MAX_PATH 256
#define PORT_LEN 5

/************************************************************************************************************************************************/
/***************************************   Utilities  *******************************************************************************************/
/************************************************************************************************************************************************/

bool operator==(MonitorRequest const & request1, MonitorRequest const & request2)
{
    return request1.session() == request2.session() && request1.timestamp() == request2.timestamp();
}

std::size_t hash_value(MonitorRequest const& request) {
    std::size_t seed = 0;
    boost::hash_combine(seed, request.session());
    boost::hash_combine(seed, request.timestampstr());
    return seed;
}

bool operator==(HistoricalCacheRequest const & request1, HistoricalCacheRequest const & request2)
{
    return request1.identity.ctx == request2.identity.ctx && request1.identity.timestamp == request2.identity.timestamp;
}

std::size_t hash_value(HistoricalCacheRequest const& request) {
    std::size_t seed = 0;
    boost::hash_combine(seed, request.identity.ctx);
    boost::hash_combine(seed, request.identity.timestamp);
    return seed;
}

/* Singleton instance */
boost::scoped_ptr<CacheManager> CacheManager::instance_;

/************************************************************************************************************************************************/
/***************************************   Initialization and shutdown  *************************************************************************/
/************************************************************************************************************************************************/
void CacheManager::init() {
  if(CacheManager::instance_.get() == NULL)
	  CacheManager::instance_.reset(new CacheManager());
}

/** The order of operations within the shutdown scenario is mandatory */
status::StatusInternal CacheManager::shutdown(bool force, bool updateClients){
	if(m_shutdownFlag){
		LOG (WARNING) << "shutdown already requested. No actions will be taken." << "\n";
		return status::StatusInternal::FINALIZATION_IN_PROGRESS;
	}

	// publish the shutdown flag to this module
	m_shutdownFlag = true;

	// Now cleanup all cache manager queues to prevent new data to be found by dispatchers on the current iteration.y
	// If any request is already on the fly, it will be canceled ASAP and there's no interest in its statistic more.
	finalize<ClientRequests, MonitorRequest>(&m_activeHighRequests, &m_highrequestsMux);
	finalize<ClientRequests, MonitorRequest>(&m_activeLowRequests, &m_lowrequestsMux);
	finalize<ClientRequests, MonitorRequest>(&m_syncRequestsQueue, &m_SyncRequestsMux);

	// finalize the history:
	// finalize<HistoryOfRequests, HistoricalCacheRequest>(&m_HistoryRequests, &m_HistoryMux);
	HistoryOfRequests().swap(m_HistoryRequests);

    // shutdown thread pools in a graceful way so that they will finish all enqueued work while will not
	// accept newly offered if happens to be offered with.
	m_shortpool.Shutdown(); // if dispatcher is on a blocking offer now, it will be unblocked after this.
	                        // if dispatcher is on blocking wait for compound request to complete blocking offering,
	                        // as compound request will be unblocked, the dispatcher will be unblocked as well.
	m_longpool.Shutdown();

	// wait for pools to complete jobs that were already on the fly
	m_shortpool.Join();
	m_longpool.Join();

	// set data condition variables for all dispatchers so that they are able to awake and read shutdown flag (see condition 1 for dispatcher).
	boost::unique_lock<boost::mutex> datalockLong(m_highrequestsMux);
	m_controlHighRequestsArrival.notify_all();
	datalockLong.unlock();

	boost::unique_lock<boost::mutex> datalockShort(m_lowrequestsMux);
	m_controlLowRequestsArrival.notify_all();
	datalockShort.unlock();

	// and wait for dispatchers to finalize:
	// wait for short requests dispatcher to finalize:
	boost::unique_lock<boost::mutex> lockshortpool(m_shortThreadIsDoneMux);
	m_shortthreadIsDoneCondition.wait(lockshortpool, [this] { return m_shortThreadIsDoneFlag; });
	lockshortpool.unlock();

	// wait for long requests dispatcher to finalize:
	boost::unique_lock<boost::mutex> locklongpool(m_longThreadIsDoneMux);
	m_longthreadIsDoneCondition.wait(locklongpool, [this] { return m_longThreadIsDoneFlag; } );
	locklongpool.unlock();

	// this is redundant due to the architecture of dispatchers working function.
	m_LowPriorityQueueThread->Join();
	m_HighPriorityQueueThread->Join();

	// cleanup all
	m_LowPriorityQueueThread.reset();
	m_HighPriorityQueueThread.reset();

	CacheManager::instance_.reset();
	return status::StatusInternal::OK;
}

/************************************************************************************************************************************************/
/***************************************   Internals  *******************************************************************************************/
/************************************************************************************************************************************************/

template<typename IndexType_, typename ItemType_>
void CacheManager::finalize(IndexType_* queue, boost::mutex* mux){
	boost::lock_guard<boost::mutex> lock(*mux);
	// Cancel everything that now in a running state
	std::for_each(queue->begin(), queue->end(), [](boost::shared_ptr<ItemType_> request){
		if(request->status() == taskOverallStatus::IN_PROGRESS)
			request->cancel(); });

	// clean the queue
	IndexType_().swap(*queue);
}

void CacheManager::dispatcherProc(dfsThreadPool* pool, int threadnum, const boost::shared_ptr<request::Task>& task ){
    if(m_shutdownFlag || task->invalidated())
    	return;
	task->operator ()();
}

/* Dispatcher may be locked in following places and so should be unlocked in one or another way:
 * - wait for request with "NOT_RUN" status appears in the queue                       (condition 1)
 * - wait on blocking Offer() operation to a bound thread pool                         (condition 2)
 * - wait for signal from compound task that those task completed its own offerings.   (condition 3)
 *
 * It routes compound request to a pool which is shared with that compound request and therefore is available
 * for compound requests offerings. As compound requests along with their subtasks should run FIFO,
 * dispatcher, once scheduled the compound task onto the pool, should wait for that task to complete its own scheduling -
 * in order to accept new compound requests and offer them to a shared pool.
 *
 * Finalization scenario:
 * dispatcher once detecting finalization flag, should stop process the bound queue of requests and go out.
 * How this happens:
 * - if it is waiting on the condition (1) - it releases the lock and go out
 * - if it dropped from Offer() - condition 2 - it simply go out
 * - if it dropped from the waiting on condition 3 - it simply make a new try and detects the finalization flag is set,
 * so no new iteration happens.
 *
 * In any case, when the main dispatcher loop finishes, dispatcher should signal the condition "dispatcher finalized".
 * Thus we know no handler exists for requests queue and release them safely.
 * */
void CacheManager::dispatchRequest(requestPriority priority){
		// select work instrumentation.
		boost::mutex*              mux;               // mutex to guard the selected collection
		ClientRequests*            requests;          // queue to analyze for arrivals
        boost::condition_variable* conditionvariable; // condition variable to wait on
        dfsThreadPool*             pool;              // pool to offer the request

        // shutdown sync:
        bool*                       shutdownFlag;      // shutdown confirmation by dispatcher
        boost::mutex*               shutdownMux;       // mutex to guard the confirmation
        boost::condition_variable*  shutdownCondition; // shutdown confirmation event

		switch(priority){
		case requestPriority::HIGH:

			mux               = &m_highrequestsMux;
			requests          = &m_activeHighRequests;
			conditionvariable = &m_controlHighRequestsArrival;
			pool              = &m_shortpool;

			shutdownFlag      = &m_shortThreadIsDoneFlag;
			shutdownMux       = &m_shortThreadIsDoneMux;
			shutdownCondition = &m_shortthreadIsDoneCondition;
			break;
		case requestPriority::LOW:

			mux               = &m_lowrequestsMux;
			requests          = &m_activeLowRequests;
			conditionvariable = &m_controlLowRequestsArrival;
			pool              = &m_longpool;

			shutdownFlag      = &m_longThreadIsDoneFlag;
			shutdownMux       = &m_longThreadIsDoneMux;
			shutdownCondition = &m_longthreadIsDoneCondition;
			break;

		case requestPriority::NOT_SET:
			return;
		}

		// do work while global shutdown flag is not received
		while(!m_shutdownFlag){
			// single request
			boost::shared_ptr<MonitorRequest>           request;
			// iterator through requests
			ClientRequests::nth_index_iterator<0>::type iterator;

			boost::unique_lock<boost::mutex> lock(*mux);
			// Wait for either shutdown happens or "not run" request detected in the supervised list of active requests
            (*conditionvariable).wait(lock, [&](){ return [&](){
            	auto it = std::find_if(requests->begin(), requests->end(),
            			[&](boost::shared_ptr<MonitorRequest> req){ return req->status() == taskOverallStatus::NOT_RUN; } );
            			if(it != requests->end())
            				return true;
            			return false;
            }() || m_shutdownFlag; });

            // if shutdown requested, interrupt everything. (Condition 1)
        	if(m_shutdownFlag){
        		lock.unlock();
        		LOG (INFO) << "dispatcher detects shutdown condition and is finalizing." << "\n";
        		break;
        	}

            // Get the top "not run" iterator from the queue of requests
        	auto it = std::find_if(requests->begin(), requests->end(),
        			[&](boost::shared_ptr<MonitorRequest> req){ return req->status() == taskOverallStatus::NOT_RUN; } );

        	if(it == requests->end()){
            	// Why we are here?
            	LOG (WARNING) << "False invitation to handle request" << "\n";
            	lock.unlock();
            	continue;
        	}
        	// here's new request to run!
        	request = (*it);
            lock.unlock();

            if(request == NULL){
            	LOG (WARNING) << "No request found!" << "\n";
            	continue;
            }

            // set "PENDING" status to this request.
            request->status(taskOverallStatus::PENDING);

            // Requests queue should be unlocked until now as further operation is blocking.
            // if there's request found, offer it to a corresponding thread pool.
            if(!pool->Offer(request)){                                                         // (Condition 2)
            	// check that the shutdown event was signaled:
            	if(m_shutdownFlag)
            		LOG (INFO) << priority << " priority requests dispatch exiting due shutdown. Thread pool was shutdown." << "\n";
            	else
            		LOG (ERROR) << priority << " priority requests dispatch exiting due to unknown reason." << "\n";
            	// go out anyway.
            	break;
            }
            // wait here until the request will finish its offering to a thread pool
            // or until the external shutdown requested.
            request->waitScheduled([&](){ return m_shutdownFlag || request->scheduled(); });
		}
		// If here, check for shutdown flag:
		if(m_shutdownFlag){
			*shutdownFlag = true;
			// if shutdown was requested, notify it was performed on this dispatcher:
			boost::lock_guard<boost::mutex> lock(*shutdownMux);
			(*shutdownCondition).notify_one();
		}
	}

void CacheManager::finalizeUserRequest(const requestIdentity& requestIdentity, const FileSystemDescriptor & fsDescriptor,
		requestPriority priority, bool cancelled, bool async ){

	if(m_shutdownFlag){
		LOG (INFO) << "finalizeUserRequest : " << "request finalization canceled. Global finalization is in progress" << "\n";
		return;
	}

	// select work instrumentation.
	boost::mutex*   mux;              // mutex to guard the selected collection
	ClientRequests* requests;         // queue to analyze for arrivals
    std::string     message;          // message to specify the queue which is handled.

	// If request is async
	if(async){
		switch(priority){
			case requestPriority::HIGH:
				mux      = &m_highrequestsMux;
				requests = &m_activeHighRequests;
				message  = "high priority queue";
				break;
			case requestPriority::LOW:
				mux      = &m_lowrequestsMux;
				requests = &m_activeLowRequests;
				message  = "low priority queue";
				break;

			case requestPriority::NOT_SET:
				LOG (WARNING) << "non-prioritized request reached finalization and cannot be fnalized." << "\n";
				return;
			}
	}
	else { // request is sync
		mux      = &m_SyncRequestsMux;
		requests = &m_syncRequestsQueue;
		message  = "sync requests eue";
	}

	// Async scenario is handled here:
	boost::mutex::scoped_lock activeLock(*mux);
	// get the request from the active requests:
	RequestsBySessionAndTimestampTag& filtered_requests = requests->get<session_timestamp_tag>();
	auto it = filtered_requests.find(boost::make_tuple(requestIdentity.timestamp, requestIdentity.ctx));

	// if anything found, remove it from the "active" requests and place it to "history":
    if(it == filtered_requests.end()){
    	// nothing to do, just log the BUG
    	LOG (ERROR) << "Finalize request. Unable to locate request in " << message << " to finalize it. Request timestamp : "
    			<< requestIdentity.timestamp << "\n";
    	return;
    }

    // if there's request found, get it before it will be removed from active requests.
    boost::shared_ptr<MonitorRequest> request = (*it);

    // and remove it from active requests:
    requests->remove_if([&](boost::shared_ptr<MonitorRequest> request) { return request->session() == requestIdentity.ctx &&
        		request->timestampstr() == requestIdentity.timestamp; });
    activeLock.unlock();

    // create the history request from this one:
    boost::shared_ptr<HistoricalCacheRequest> historical(new HistoricalCacheRequest());
    historical->canceled    = (request->status() == taskOverallStatus::CANCELED_CONFIRMED ||
    						   request->status() == taskOverallStatus::CANCELATION_SENT);
    historical->identity    = requestIdentity;
    historical->status      = request->status();
    historical->performance = request->performance();
    historical->progress    = request->progress();
    historical->succeed     = (request->status() == taskOverallStatus::COMPLETED_OK);

    boost::unique_lock<boost::mutex> historyLock(m_HistoryMux);
    // check that the history size limit is not exceeded
    if(m_HistoryRequests.size() >= constants::HISTORY_ENTRIES_LIMIT * 2){
    	// remove half of history requests content:
    	int iterations = 0;
    	for(auto iter = m_HistoryRequests.begin();
    			(iterations <= constants::HISTORY_ENTRIES_LIMIT) && (iter != m_HistoryRequests.end()); iterations++){
    		m_HistoryRequests.erase(iter);
    		iter++;
    	}
    }
    // now add it to History, add it first as most recent:
    m_HistoryRequests.push_front(std::move(historical));
    historyLock.unlock();

    LOG (INFO) << "Finalize request. Request was moved to history. Status : " << request->status() << "; Request timestamp : " << requestIdentity.timestamp << "\n";
}

/************************************************************************************************************************************************/
/***************************************   API  *************************************************************************************************/
/************************************************************************************************************************************************/

status::StatusInternal CacheManager::cacheEstimate(SessionContext session, const FileSystemDescriptor & fsDescriptor, const DataSet& files, time_t& time,
		   CacheEstimationCompletedCallback callback, requestIdentity & requestIdentity, bool async) {

	if(m_shutdownFlag){
		LOG (INFO) << "cacheEstimate : " << "request will not be handled. Finalization is in progress" << "\n";
		return status::StatusInternal::FINALIZATION_IN_PROGRESS;
	}

    // subscribe the request to come back to cache manager when it will be finished for further management
    DataSetRequestCompletionFunctor functor = boost::bind(boost::mem_fn(&CacheManager::finalizeUserRequest), this, _1, _2, _3, _4, _5);

    // create the task "CacheEstimationTask"
    boost::shared_ptr<MonitorRequest> request(new request::EstimateDatasetTask(callback, functor, functor, session, fsDescriptor, m_syncModule,
    		&m_shortpool, files, async));

    // assign the request identity
    requestIdentity.ctx = session;
    requestIdentity.timestamp = request->timestampstr();

    if(async){
    	boost::lock_guard<boost::mutex> lock(m_highrequestsMux);
    	// send task to the queue for further processing:
    	auto it = m_activeHighRequests.push_back(request);
    	// if there was a problem to insert the request, reply it
    	if(!it.second){
    		LOG (WARNING) << "Unable to schedule estimate request for processing." << "\n";
    		return status::StatusInternal::OPERATION_ASYNC_REJECTED;
    	}
    	// notify new data arrival
    	m_controlHighRequestsArrival.notify_all();
    	// if async, go out immediately:
		return status::StatusInternal::OPERATION_ASYNC_SCHEDULED;
    }

    // request is sync and should be marked as that so that it will not be handled by scheduler
    boost::unique_lock<boost::mutex> lock(m_SyncRequestsMux);
    // now add it to History, add it first as most recent:
    auto it = m_syncRequestsQueue.push_back(request);
    lock.unlock();

	// if there was a problem to insert the request, reply it
	if(!it.second){
		LOG (WARNING) << "Unable to schedule estimate request for processing." << "\n";
		std::cout << "Unable to schedule estimate request for processing.\n";
		return status::StatusInternal::OPERATION_ASYNC_REJECTED;
	}

    // and executed on the caller thread:
    request->operator ()();
	// in a sync way, need to wait for task completion.
    // check for request status:
    taskOverallStatus status = request->status();
	return status == taskOverallStatus::COMPLETED_OK ? status::StatusInternal::OK : status::StatusInternal::REQUEST_FAILED;
}

status::StatusInternal CacheManager::cachePrepareData(SessionContext session, const FileSystemDescriptor & fsDescriptor,
		const DataSet& files, PrepareCompletedCallback callback, requestIdentity & requestIdentity){

	if(m_shutdownFlag){
		LOG (INFO) << "cachePrepareData : " << "request will not be handled. Finalization is in progress" << "\n";
		return status::StatusInternal::FINALIZATION_IN_PROGRESS;
	}

    // subscribe the request to come back to cache manager when it will be finished for further management
    DataSetRequestCompletionFunctor functor = boost::bind(boost::mem_fn(&CacheManager::finalizeUserRequest), this, _1, _2, _3, _4, _5);

    // create the task "Cache Prepare Task"
    boost::shared_ptr<MonitorRequest> request(new request::PrepareDatasetTask(callback, functor, functor, session, fsDescriptor, m_syncModule, &m_longpool, files));

    // assign the request identity
    requestIdentity.ctx = session;
    requestIdentity.timestamp = request->timestampstr();

    {
    	boost::lock_guard<boost::mutex> lock(m_lowrequestsMux);
    	// send task to the queue for further processing:
    	auto it = m_activeLowRequests.push_back(request);
    	// if there was a problem to insert the request, reply it
    	if(!it.second){
    		LOG (WARNING) << "Unable to schedule prepare request for processing." << "\n";
    		std::cout << "Unable to schedule prepare request for processing.\n";
    		return status::StatusInternal::OPERATION_ASYNC_REJECTED;
    	}
    	// notify new data arrival
    	m_controlLowRequestsArrival.notify_all();
    }

    // if async, go out immediately:
    return status::StatusInternal::OPERATION_ASYNC_SCHEDULED;
}

status::StatusInternal CacheManager::cacheCancelPrepareData(const requestIdentity & requestIdentity){

	if(m_shutdownFlag){
		LOG (INFO) << "cacheCancelPrepareData : " << "request will not be handled. Finalization is in progress" << "\n";
		return status::StatusInternal::FINALIZATION_IN_PROGRESS;
	}

	boost::unique_lock<boost::mutex> lock(m_lowrequestsMux);

	// get the request from the active requests:
	RequestsBySessionAndTimestampTag& requests = m_activeLowRequests.get<session_timestamp_tag>();
	auto it = requests.find(boost::make_tuple(requestIdentity.timestamp, requestIdentity.ctx));

	// if nothing found, report the warning about missed request to cancel
	if(it == requests.end()){
		// nothing to do, just log the BUG
		LOG (WARNING) << "Unable to locate request to cancel it, no actions will be taken. Request timestamp : " << requestIdentity.timestamp << "\n";
		return status::StatusInternal::REQUEST_IS_NOT_FOUND;
	}

	// if there's request found, send the cancellation request to it
	boost::shared_ptr<MonitorRequest> request = (*it);
	lock.unlock();

	// cancel the task async
	taskOverallStatus status = request->cancel(true);
	LOG (INFO) << "Request was cancelled. Cancelation status :\"" << status << ";  Request timestamp : " << requestIdentity.timestamp << "; Request status : " << request->status() << "\n";

	return status::StatusInternal::OK;
}

status::StatusInternal CacheManager::cacheCheckPrepareStatus(const requestIdentity & requestIdentity,
		std::list<boost::shared_ptr<FileProgress> > & progress, request_performance& performance){

	if(m_shutdownFlag){
		LOG (INFO) << "cacheCheckPrepareStatus : " << "request will not be handled. Finalization is progress" << "\n";
		return status::StatusInternal::FINALIZATION_IN_PROGRESS;
	}
	LOG (INFO) << "Check Prepare status for Request timestamp : " << requestIdentity.timestamp << "\n";
	boost::unique_lock<boost::mutex> lock(m_lowrequestsMux);

	// get the request from the active requests:
	RequestsBySessionAndTimestampTag& requests = m_activeLowRequests.get<session_timestamp_tag>();
	auto it = requests.find(boost::make_tuple(requestIdentity.timestamp, requestIdentity.ctx));

	// if nothing found in "active requests", log this and try to find in "history"
	if(it != requests.end()){
		// if there's request found, query it for progress and report back to client
		boost::shared_ptr<MonitorRequest> request = (*it);
		lock.unlock();

		progress = request->progress();
		performance = request->performance();

		LOG (INFO) << "Request is found among \"Active\". Request timestamp : " << requestIdentity.timestamp << "; Request status : " << request->status() << "\n";
	    return status::StatusInternal::OK;
	}
	lock.unlock();

	boost::unique_lock<boost::mutex> hilock(m_HistoryMux);

	// get the request from the history requests:
	HistoricalRequestsBySessionAndTimestampTag& historical = m_HistoryRequests.get<session_timestamp_tag>();
	auto hit = historical.find(boost::make_tuple(requestIdentity.timestamp, requestIdentity.ctx));

	// if nothing found in "active requests", log this and try to find in "history"
	if(hit != historical.end()){
		// if there's request found, query it for progress and report back to client
		boost::shared_ptr<HistoricalCacheRequest> request = (*hit);
		hilock.unlock();

		progress = request->progress;
		performance = request->performance;

		LOG (INFO) << "Request is found in \"History\". Request timestamp : " << requestIdentity.timestamp << "; Request status : " << request->status << "\n";
	    return status::StatusInternal::OK;
	}
	hilock.unlock();

	LOG (WARNING) << "Request is not found! Request timestamp : " << requestIdentity.timestamp << "\n";
	// TODO : check for requested request timestamp. If it less than auto-cleanup treshold, report the error in logging level.
	return status::StatusInternal::REQUEST_IS_NOT_FOUND;
}

} /** namespace impala */

ext: cc

max_stars_repo_name: ImpalaToGo/ImpalaToGo

max_issues_repo_name: ImpalaToGo/ImpalaToGo

max_forks_repo_name: ImpalaToGo/ImpalaToGo


text:
/*
 * MIT License
 *
 * Copyright (c) 2019 Denis Kovalchuk
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "client.hpp"
#include "ftp_exception.hpp"
#include "detail/connection_exception.hpp"
#include <filesystem>
#include <fstream>
#include <boost/lexical_cast.hpp>

namespace ftp
{
using std::string;
using std::make_unique;
using std::optional;
using std::ifstream;
using std::ofstream;
using std::unique_ptr;
using std::ios_base;
using std::pair;
using std::make_pair;
using std::nullopt;
using std::make_optional;

using namespace ftp::detail;

client::client(client::event_observer *observer)
{
    if (observer)
    {
        observers_.push_back(observer);
    }
}

bool client::open(const string & hostname, uint16_t port)
{
    try
    {
        control_connection_.open(hostname, port);

        reply_t reply = recv();

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::is_open()
{
    try
    {
        return control_connection_.is_open();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::login(const string & username, const string & password)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("USER " + username);

        if (reply.status_code == 331)
        {
            /* 331 User name okay, need password. */
            reply = send_command("PASS " + password);
        }
        else if (reply.status_code == 332)
        {
            /* 332 Need account for login.
             * Sorry, we don't support ACCT command.
             */
        }

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::cd(const string & remote_directory)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("CWD " + remote_directory);

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::ls(const optional<string> & remote_directory)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        string command;

        if (remote_directory)
        {
            command = "LIST " + remote_directory.value();
        }
        else
        {
            command = "LIST";
        }

        unique_ptr<data_connection> data_connection = establish_data_connection(command);

        if (!data_connection)
        {
            return false;
        }

        string file_list = data_connection->recv();
        report_reply(file_list);

        /* Don't keep the data connection. */
        data_connection->close();

        reply_t reply = recv();

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::upload(const string & local_file, const string & remote_file)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        ifstream file(local_file, ios_base::binary);

        if (!file)
        {
            throw ftp_exception("Cannot open file '%1%'.", local_file);
        }

        unique_ptr<data_connection> data_connection = establish_data_connection("STOR " + remote_file);

        if (!data_connection)
        {
            return false;
        }

        data_connection->send(file);

        /* Don't keep the data connection. */
        data_connection->close();

        reply_t reply = recv();

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::download(const string & remote_file, const string & local_file)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        if (std::filesystem::exists(local_file))
        {
            throw ftp_exception("The file '%1%' already exists.", local_file);
        }

        ofstream file(local_file, ios_base::binary);

        if (!file)
        {
            throw ftp_exception("Cannot create file %1%.", local_file);
        }

        unique_ptr<data_connection> data_connection = establish_data_connection("RETR " + remote_file);

        if (!data_connection)
        {
            return false;
        }

        data_connection->recv(file);

        /* Don't keep the data connection. */
        data_connection->close();

        reply_t reply = recv();

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::pwd()
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("PWD");

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::mkdir(const string & directory_name)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("MKD " + directory_name);

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::rmdir(const string & directory_name)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("RMD " + directory_name);

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::rm(const string & remote_file)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("DELE " + remote_file);

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::binary()
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("TYPE I");

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::size(const string & remote_file)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("SIZE " + remote_file);

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::stat(const optional<string> & remote_file)
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        string command;

        if (remote_file)
        {
            command = "STAT " + remote_file.value();
        }
        else
        {
            command = "STAT";
        }

        reply_t reply = send_command(command);

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::system()
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("SYST");

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::noop()
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("NOOP");

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

bool client::close()
{
    try
    {
        if (!is_open())
        {
            throw ftp_exception("Connection is not open.");
        }

        reply_t reply = send_command("QUIT");

        control_connection_.close();

        return reply.is_positive();
    }
    catch (const connection_exception & ex)
    {
        reset_connection();
        throw ftp_exception(ex);
    }
}

reply_t client::send_command(const string & command)
{
    control_connection_.send(command);

    reply_t reply = control_connection_.recv();

    report_reply(reply);

    return reply;
}

reply_t client::recv()
{
    reply_t reply = control_connection_.recv();

    report_reply(reply);

    return reply;
}

void client::reset_connection()
{
    try
    {
        control_connection_.close();
    }
    catch (...)
    {
    }
}

unique_ptr<data_connection> client::establish_data_connection(const string & command)
{
    if (!is_open())
    {
        throw ftp_exception("Connection is not open.");
    }

    reply_t reply = send_command("EPSV");

    if (!reply.is_positive())
    {
        return nullptr;
    }

    uint16_t port;
    if (!try_parse_server_port(reply.status_line, port))
    {
        throw ftp_exception("Cannot parse server port from '%1%'.", reply.status_line);
    }

    unique_ptr<data_connection> connection = make_unique<data_connection>(control_connection_.ip(), port);

    connection->open();

    reply = send_command(command);

    if (!reply.is_positive())
    {
        return nullptr;
    }

    return connection;
}

/* The text returned in response to the EPSV command MUST be:
 *
 *     <text indicating server is entering extended passive mode> \
 *       (<d><d><d><tcp-port><d>)
 *
 * The first two fields contained in the parenthesis MUST be blank.  The
 * third field MUST be the string representation of the TCP port number
 * on which the server is listening for a data connection.  The network
 * protocol used by the data connection will be the same network
 * protocol used by the control connection.  In addition, the network
 * address used to establish the data connection will be the same
 * network address used for the control connection.  An example response
 * string follows:
 *
 *     Entering Extended Passive Mode (|||6446|)
 *
 * RFC 2428: https://tools.ietf.org/html/rfc2428
 */
bool client::try_parse_server_port(const string & epsv_reply, uint16_t & port)
{
    size_t begin = epsv_reply.find('|');
    if (begin == string::npos)
    {
        return false;
    }

    /* Skip '|||' characters. */
    begin += 3;
    if (begin >= epsv_reply.size())
    {
        return false;
    }

    size_t end = epsv_reply.rfind('|');
    if (end == string::npos)
    {
        return false;
    }

    if (end <= begin)
    {
        return false;
    }

    string port_str = epsv_reply.substr(begin, end - begin);

    return boost::conversion::try_lexical_convert(port_str, port);
}

void client::subscribe(event_observer *observer)
{
    observers_.push_back(observer);
}

void client::unsubscribe(event_observer *observer)
{
    observers_.remove(observer);
}

void client::report_reply(const string & reply)
{
    for (const auto & observer : observers_)
    {
        if (observer)
            observer->on_reply(reply);
    }
}

void client::report_reply(const reply_t & reply)
{
    for (const auto & observer : observers_)
    {
        if (observer)
            observer->on_reply(reply.status_line);
    }
}

} // namespace ftp

ext: cpp

max_stars_repo_name: deniskovalchuk/ftp-client

max_issues_repo_name: deniskovalchuk/ftp-client

max_forks_repo_name: deniskovalchuk/ftp-client


text:
// Copyright (C) 2008-2011 Anders Logg and Ola Skavhaug
//
// This file is part of DOLFIN.
//
// DOLFIN is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// DOLFIN 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
//
// Modified by Niclas Jansson 2009.
// Modified by Garth N. Wells 2010.
//
// First added:  2008-08-12
// Last changed: 2011-11-14

#include <ufc.h>
#include <boost/random.hpp>
#include <boost/unordered_map.hpp>

#include <dolfin/common/Timer.h>
#include <dolfin/log/log.h>
#include <dolfin/mesh/BoundaryMesh.h>
#include <dolfin/mesh/Facet.h>
#include <dolfin/mesh/Mesh.h>
#include <dolfin/mesh/Vertex.h>
#include "DofMap.h"
#include "UFCCell.h"
#include "UFCMesh.h"
#include "DofMapBuilder.h"

using namespace dolfin;

//-----------------------------------------------------------------------------
void DofMapBuilder::build(DofMap& dofmap, const Mesh& dolfin_mesh,
                          const UFCMesh& ufc_mesh, bool distributed)
{
  // Start timer for dofmap initialization
  Timer t0("Init dofmap");

  // Create space for dof map
  dofmap._dofmap.resize(dolfin_mesh.num_cells());

  dofmap._off_process_owner.clear();

  dolfin_assert(dofmap._ufc_dofmap);

  std::cout << "DofMapBuilder: initialized" << std::endl;

  // Build dofmap from ufc::dofmap
  dolfin::UFCCell ufc_cell(dolfin_mesh);
  std::cout << "Processing cells: ";
  for (dolfin::CellIterator cell(dolfin_mesh); !cell.end(); ++cell)
  {
    std::cout << cell->index() << ",";
    // Update UFC cell
    ufc_cell.update(*cell);

    // Get standard local dimension
    const unsigned int local_dim = dofmap._ufc_dofmap->local_dimension(ufc_cell);
    dofmap._dofmap[cell->index()].resize(local_dim);

    // Tabulate standard UFC dof map
    dofmap._ufc_dofmap->tabulate_dofs(&dofmap._dofmap[cell->index()][0],
                                      ufc_mesh, ufc_cell);
  }
  std::cout << std::endl;
  std::cout << "DofMapBuilder: dofmap built" << std::endl;

  // Build (renumber) dofmap when running in parallel
  if (distributed)
  {
    // Build set of global dofs
    const set global_dofs = compute_global_dofs(dofmap, dolfin_mesh);

    // Build distributed dof map
    build_distributed(dofmap, global_dofs, dolfin_mesh);
  }
  else
    dofmap._ownership_range = std::make_pair(0, dofmap.global_dimension());
}
//-----------------------------------------------------------------------------
void DofMapBuilder::build_distributed(DofMap& dofmap,
                                      const DofMapBuilder::set& global_dofs,
                                      const Mesh& mesh)
{
  // Create data structures
  DofMapBuilder::set owned_dofs, shared_owned_dofs, shared_unowned_dofs;

  // Computed owned and shared dofs (and owned and un-owned)
  compute_ownership(owned_dofs, shared_owned_dofs, shared_unowned_dofs,
                    dofmap, global_dofs, mesh);

  // Renumber dofs owned dofs and received new numbering for unowned shared dofs
  parallel_renumber(owned_dofs, shared_owned_dofs, shared_unowned_dofs,
                    dofmap, mesh);
}
//-----------------------------------------------------------------------------
void DofMapBuilder::compute_ownership(set& owned_dofs, set& shared_owned_dofs,
                                      set& shared_unowned_dofs,
                                      const DofMap& dofmap,
                                      const DofMapBuilder::set& global_dofs,
                                      const Mesh& mesh)
{
  log(TRACE, "Determining dof ownership for parallel dof map");

  // Create a radom number generator for ownership 'voting'
  boost::mt19937 engine(MPI::process_number());
  boost::uniform_int<> distribution(0, 100000000);
  boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rng(engine, distribution);

  // Clear data structures
  owned_dofs.clear();
  shared_owned_dofs.clear();
  shared_unowned_dofs.clear();

  // Data structures for computing ownership
  boost::unordered_map<uint, uint> dof_vote;
  std::vector<uint> facet_dofs(dofmap.num_facet_dofs());

  // Communication buffer
  std::vector<uint> send_buffer;

  // Extract the interior boundary
  BoundaryMesh interior_boundary;
  interior_boundary.init_interior_boundary(mesh);

  // Build set of dofs on process boundary (assume all are owned by this process)
  const MeshFunction<unsigned int>& cell_map = interior_boundary.cell_map();
  if (cell_map.size() > 0)
  {
    for (CellIterator bc(interior_boundary); !bc.end(); ++bc)
    {
      // Get boundary facet
      Facet f(mesh, cell_map[*bc]);

      // Get cell to which facet belongs (pick first)
      Cell c(mesh, f.entities(mesh.topology().dim())[0]);

      // Tabulate dofs on cell
      const std::vector<uint>& cell_dofs = dofmap.cell_dofs(c.index());

      // Tabulate which dofs are on the facet
      dofmap.tabulate_facet_dofs(&facet_dofs[0], c.index(f));

      // Insert shared dofs into set and assign a 'vote'
      for (uint i = 0; i < dofmap.num_facet_dofs(); i++)
      {
        if (shared_owned_dofs.find(cell_dofs[facet_dofs[i]]) == shared_owned_dofs.end())
        {
          shared_owned_dofs.insert(cell_dofs[facet_dofs[i]]);
          dof_vote[cell_dofs[facet_dofs[i]]] = rng();

          send_buffer.push_back(cell_dofs[facet_dofs[i]]);
          send_buffer.push_back(dof_vote[cell_dofs[facet_dofs[i]]]);
        }
      }
    }
  }

  // Decide ownership of shared dofs
  const uint num_proc = MPI::num_processes();
  const uint proc_num = MPI::process_number();
  //const uint max_recv = MPI::max(send_buffer.size());
  std::vector<uint> recv_buffer;
  for (uint k = 1; k < MPI::num_processes(); ++k)
  {
    const uint src  = (proc_num - k + num_proc) % num_proc;
    const uint dest = (proc_num + k) % num_proc;
    MPI::send_recv(send_buffer, dest, recv_buffer, src);

    for (uint i = 0; i < recv_buffer.size(); i += 2)
    {
      const uint received_dof  = recv_buffer[i];
      const uint received_vote = recv_buffer[i + 1];
      if (shared_owned_dofs.find(received_dof) != shared_owned_dofs.end())
      {
        // Move dofs with higher ownership votes from shared to shared but not owned
        if (received_vote < dof_vote[received_dof])
        {
          shared_unowned_dofs.insert(received_dof);
          shared_owned_dofs.erase(received_dof);
        }
        else if (received_vote == dof_vote[received_dof])
        {
          // FIXME: Eventually replace this with a more robust condition. It's
          // good for testing that ownership of shared dofs is spread roughly
          // equally
          dolfin_error("DofMapBuilder.cpp",
                       "compute mapping of degrees of freedom",
                       "Cannot decide on dof ownership; votes are equal");
        }
      }
    }
  }

  // Add/remove global dofs to relevant sets (process 0 owns local dofs)
  if (MPI::process_number() == 0)
  {
    shared_owned_dofs.insert(global_dofs.begin(), global_dofs.end());
    for (set::const_iterator dof = global_dofs.begin(); dof != global_dofs.begin(); ++dof)
    {
      set::const_iterator _dof = shared_unowned_dofs.find(*dof);
      if (_dof != shared_unowned_dofs.end())
        shared_unowned_dofs.erase(_dof);
    }
  }
  else
  {
    shared_unowned_dofs.insert(global_dofs.begin(), global_dofs.end());
    for (set::const_iterator dof = global_dofs.begin(); dof != global_dofs.begin(); ++dof)
    {
      set::const_iterator _dof = shared_owned_dofs.find(*dof);
      if (_dof != shared_owned_dofs.end())
        shared_owned_dofs.erase(_dof);
    }
  }

  // Mark all shared and owned dofs as owned by the processes
  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    const std::vector<uint>& cell_dofs = dofmap.cell_dofs(cell->index());
    const uint cell_dimension = dofmap.cell_dimension(cell->index());
    for (uint i = 0; i < cell_dimension; ++i)
    {
      // Mark dof as owned if in unowned set
      if (shared_unowned_dofs.find(cell_dofs[i]) == shared_unowned_dofs.end())
        owned_dofs.insert(cell_dofs[i]);
    }
  }

  // Check that sum of locally owned dofs is equal to global dimension
  const uint _owned_dim = owned_dofs.size();
  dolfin_assert(MPI::sum(_owned_dim) == dofmap.global_dimension());

  log(TRACE, "Finished determining dof ownership for parallel dof map");
}
//-----------------------------------------------------------------------------
void DofMapBuilder::parallel_renumber(const set& owned_dofs,
                             const set& shared_owned_dofs,
                             const set& shared_unowned_dofs,
                             DofMap& dofmap, const Mesh& mesh)
{
  log(TRACE, "Renumber dofs for parallel dof map");

  // FIXME: Handle double-renumbered dof map
  if (dofmap.ufc_map_to_dofmap.size() > 0)
  {
    dolfin_error("DofMapBuilder.cpp",
                 "compute parallel renumbering of degrees of freedom",
                 "The degree of freedom mapping cannot (yet) be renumbered twice");
  }

  const std::vector<std::vector<uint> >& old_dofmap = dofmap._dofmap;
  std::vector<std::vector<uint> > new_dofmap(old_dofmap.size());
  dolfin_assert(old_dofmap.size() == mesh.num_cells());

  // Compute offset for owned and non-shared dofs
  const uint process_offset = MPI::global_offset(owned_dofs.size(), true);

  // Clear some data
  dofmap._off_process_owner.clear();

  // Map from old to new index for dofs
  boost::unordered_map<uint, uint> old_to_new_dof_index;

  // Renumber owned dofs and buffer dofs that are owned but shared with another
  // process
  uint counter = 0;
  std::vector<uint> send_buffer;
  for (set_iterator owned_dof = owned_dofs.begin(); owned_dof != owned_dofs.end(); ++owned_dof, counter++)
  {
    // Set new dof number
    old_to_new_dof_index[*owned_dof] = process_offset + counter;

    // Update UFC-to-renumbered map for new number
    dofmap.ufc_map_to_dofmap[*owned_dof] = process_offset + counter;

    // If this dof is shared and owned, buffer old and new index for sending
    if (shared_owned_dofs.find(*owned_dof) != shared_owned_dofs.end())
    {
      send_buffer.push_back(*owned_dof);
      send_buffer.push_back(process_offset + counter);
    }
  }

  // Exchange new dof numbers for dofs that are shared
  const uint num_proc = MPI::num_processes();
  const uint proc_num = MPI::process_number();
  //const uint max_recv = MPI::max(send_buffer.size());
  std::vector<uint> recv_buffer;
  for (uint k = 1; k < MPI::num_processes(); ++k)
  {
    const uint src  = (proc_num - k + num_proc) % num_proc;
    const uint dest = (proc_num + k) % num_proc;
    MPI::send_recv(send_buffer, dest, recv_buffer, src);

    // Add dofs renumbered by another process to the old-to-new map
    for (uint i = 0; i < recv_buffer.size(); i += 2)
    {
      const uint received_old_dof_index = recv_buffer[i];
      const uint received_new_dof_index = recv_buffer[i + 1];

      // Check if this process has shared dof (and is not the owner)
      if (shared_unowned_dofs.find(received_old_dof_index) != shared_unowned_dofs.end())
      {
        // Add to old-to-new dof map
        old_to_new_dof_index[received_old_dof_index] = received_new_dof_index;

        // Store map from off-process dof to owner
        dofmap._off_process_owner[received_new_dof_index] = src;

        // Update UFC-to-renumbered map
        dofmap.ufc_map_to_dofmap[received_old_dof_index] = received_new_dof_index;
      }
    }
  }

  // Build new dof map
  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    const uint cell_index = cell->index();
    const uint cell_dimension = dofmap.cell_dimension(cell_index);

    // Resize cell map and insert dofs
    new_dofmap[cell_index].resize(cell_dimension);
    for (uint i = 0; i < cell_dimension; ++i)
    {
      const uint old_index = old_dofmap[cell_index][i];
      new_dofmap[cell_index][i] = old_to_new_dof_index[old_index];
    }
  }

  // Set new dof map
  dofmap._dofmap = new_dofmap;

  // Set ownership range
  dofmap._ownership_range = std::make_pair<uint, uint>(process_offset, process_offset + owned_dofs.size());

  log(TRACE, "Finished renumbering dofs for parallel dof map");
}
//-----------------------------------------------------------------------------
DofMapBuilder::set DofMapBuilder::compute_global_dofs(const DofMap& dofmap,
                                                       const Mesh& dolfin_mesh)
{
  // Wrap UFC dof map
  boost::shared_ptr<const ufc::dofmap> _dofmap(dofmap._ufc_dofmap.get(),
                                               NoDeleter());

  // Create UFCMesh
  const UFCMesh ufc_mesh(dolfin_mesh);

  // Compute global dof indices
  uint offset = 0;
  set global_dof_indices;
  compute_global_dofs(global_dof_indices, offset, _dofmap, dolfin_mesh, ufc_mesh);

  return global_dof_indices;
}
//-----------------------------------------------------------------------------
void DofMapBuilder::compute_global_dofs(DofMapBuilder::set& global_dofs,
                            uint& offset,
                            boost::shared_ptr<const ufc::dofmap> dofmap,
                            const Mesh& dolfin_mesh, const UFCMesh& ufc_mesh)
{
  dolfin_assert(dofmap);
  const uint D = dolfin_mesh.topology().dim();

  if (dofmap->num_sub_dofmaps() == 0)
  {
    // Check if dofmap is for global dofs
    bool global_dof = true;
    for (uint d = 0; d <= D; ++d)
    {
      if (dofmap->needs_mesh_entities(d))
      {
        global_dof = false;
        break;
      }
    }

    if (global_dof)
    {
      // Check that we have just one dof
      if (dofmap->global_dimension() != 1)
      {
        dolfin_error("DofMapBuilder.cpp",
                     "compute global degrees of freedom",
                     "Global degree of freedom has dimension != 1");
      }

      boost::scoped_ptr<ufc::mesh> ufc_mesh(new ufc::mesh);
      boost::scoped_ptr<ufc::cell> ufc_cell(new ufc::cell);
      uint dof = 0;
      dofmap->tabulate_dofs(&dof, *ufc_mesh, *ufc_cell);

      // Insert global dof index
      std::pair<DofMapBuilder::set::iterator, bool> ret = global_dofs.insert(dof + offset);
      if (!ret.second)
      {
        dolfin_error("DofMapBuilder.cpp",
                     "compute global degrees of freedom",
                     "Global degree of freedom already exists");
      }
    }
  }
  else
  {
    for (uint i = 0; i < dofmap->num_sub_dofmaps(); ++i)
    {
      // Extract sub-dofmap and intialise
      boost::shared_ptr<ufc::dofmap> sub_dofmap(dofmap->create_sub_dofmap(i));
      DofMap::init_ufc_dofmap(*sub_dofmap, ufc_mesh, dolfin_mesh);

      compute_global_dofs(global_dofs, offset, sub_dofmap, dolfin_mesh,
                          ufc_mesh);

      // Get offset
      if (sub_dofmap->num_sub_dofmaps() == 0)
        offset += sub_dofmap->global_dimension();
    }
  }
}
//-----------------------------------------------------------------------------

max_stars_repo_name: szmurlor/fiver

max_issues_repo_name: szmurlor/fiver

max_forks_repo_name: szmurlor/fiver


text:
// Copyright Nick Thompson, 2021
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MATH_INTERPOLATORS_BEZIER_POLYNOMIAL_HPP
#define BOOST_MATH_INTERPOLATORS_BEZIER_POLYNOMIAL_HPP
#include <memory>
#include <boost/math/interpolators/detail/bezier_polynomial_detail.hpp>

#ifdef BOOST_MATH_NO_THREAD_LOCAL_WITH_NON_TRIVIAL_TYPES
#warning "Thread local storage support is necessary for the Bezier polynomial class to work."
#endif

namespace boost::math::interpolators {

template <class RandomAccessContainer>
class bezier_polynomial
{
public:
    using Point = typename RandomAccessContainer::value_type;
    using Real = typename Point::value_type;
    using Z = typename RandomAccessContainer::size_type;

    bezier_polynomial(RandomAccessContainer && control_points)
    : m_imp(std::make_shared<detail::bezier_polynomial_imp<RandomAccessContainer>>(std::move(control_points)))
    {
    }

    inline Point operator()(Real t) const
    {
        return (*m_imp)(t);
    }

    inline Point prime(Real t) const
    {
        return m_imp->prime(t);
    }

    void edit_control_point(Point const & p, Z index)
    {
        m_imp->edit_control_point(p, index);
    }

    RandomAccessContainer const & control_points() const
    {
        return m_imp->control_points();
    }

    friend std::ostream& operator<<(std::ostream& out, bezier_polynomial<RandomAccessContainer> const & bp) {
        out << *bp.m_imp;
        return out;
    }

private:
    std::shared_ptr<detail::bezier_polynomial_imp<RandomAccessContainer>> m_imp;
};

}
#endif

ext: hpp

max_stars_repo_name: oleg-alexandrov/math

max_issues_repo_name: oleg-alexandrov/math

max_forks_repo_name: oleg-alexandrov/math


text:
#include <catch.hpp>
#include <Spirit/State.h>
#include <Spirit/System.h>
#include <Spirit/Simulation.h>
#include <Spirit/Configurations.h>
#include <Spirit/Hamiltonian.h>
#include <Spirit/Constants.h>
#include <Spirit/Parameters.h>
#include <data/State.hpp>
#include <Eigen/Dense>
#include <Eigen/Core>
#include <iostream>
#include <iomanip>
#include <sstream>

TEST_CASE( "Larmor Precession","[physics]" )
{
    // Input file
    auto inputfile = "core/test/input/physics_larmor.cfg";

    // Create State
    auto state = std::shared_ptr<State>( State_Setup( inputfile ), State_Delete );

    // Choose method
    auto method = "LLG";

    // Solvers to be tested
    std::vector<const char *>  solvers{ "Heun", "Depondt", "SIB" };

    // Set up one the initial direction of the spin
    float init_direction[3] = { 1., 0., 0. };                // vec parallel to x-axis
    Configuration_Domain( state.get(), init_direction );     // set spin parallel to x-axis

    // Assure that the initial direction is set
    // (note: this pointer will stay valid throughout this test)
    auto direction = System_Get_Spin_Directions( state.get() );
    REQUIRE( direction[0] == 1 );
    REQUIRE( direction[1] == 0 );
    REQUIRE( direction[2] == 0 );

    // Make sure that mu_s is the same as the one define in input file
    float mu_s;
    Hamiltonian_Get_mu_s( state.get(), &mu_s );
    REQUIRE( mu_s == 2 );

    // Get the magnitude of the magnetic field ( it has only z-axis component )
    float B_mag;
    float normal[3];
    Hamiltonian_Get_Field( state.get(), &B_mag, normal );

    // Get time step of method
    scalar damping = 0.3;
    float tstep = Parameters_Get_LLG_Time_Step( state.get() );
    Parameters_Set_LLG_Damping( state.get(), damping );

    scalar dtg = tstep * Constants_gamma() / ( 1.0 + damping*damping );

    for( auto opt : solvers )
    {
        // Set spin parallel to x-axis
        Configuration_Domain( state.get(), init_direction );

        for( int i=0; i<100; i++ )
        {
            INFO( std::string( opt ) << " failed spin trajectory test at iteration " << i );

            // A single iteration
            Simulation_SingleShot( state.get(), method, opt );

            // Expected spin orientation
            // TODO: the step size should not be scaled by mu_s
            scalar phi_expected = mu_s * dtg * (i+1) * B_mag;
            scalar sz_expected  = std::tanh( mu_s * damping * dtg * (i+1) * B_mag );
            scalar rxy_expected = std::sqrt( 1-sz_expected*sz_expected );
            scalar sx_expected  = std::cos(phi_expected) * rxy_expected;

            REQUIRE( Approx(direction[0]) == sx_expected );
            REQUIRE( Approx(direction[2]) == sz_expected );
        }
    }
}

TEST_CASE( "Finite Differences", "[physics]" )
{
    // Hamiltonians to be tested
    std::vector<const char *>  hamiltonians{ "core/test/input/fd_pairs.cfg" };
                                             //"core/test/input/fd_neighbours",
                                             //"core/test/input/fd_gaussian.cfg"};
    for( auto ham: hamiltonians )
    {
        INFO( " Testing " << ham );

        // create state
        auto state = std::shared_ptr<State>( State_Setup( ham ), State_Delete );

        Configuration_Random( state.get() );

        auto& vf = *state->active_image->spins;
        auto grad = vectorfield( state->nos );
        auto grad_fd = vectorfield( state->nos );

        state->active_image->hamiltonian->Gradient_FD( vf, grad_fd );
        state->active_image->hamiltonian->Gradient( vf, grad );

        for( int i=0; i<state->nos; i++)
            REQUIRE( grad_fd[i].isApprox( grad[i] ) );

        auto hessian = MatrixX( 3*state->nos, 3*state->nos );
        auto hessian_fd = MatrixX( 3*state->nos, 3*state->nos );

        state->active_image->hamiltonian->Hessian_FD( vf, hessian_fd );
        state->active_image->hamiltonian->Hessian( vf, hessian );

        REQUIRE( hessian_fd.isApprox( hessian ) );
    }
}

max_stars_repo_name: Zeleznyj/spirit

max_issues_repo_name: Zeleznyj/spirit

max_forks_repo_name: Zeleznyj/spirit


text:
//==============================================================================
//          Copyright 2015 J.T.  Lapreste
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef BOOST_SIMD_BITWISE_FUNCTIONS_SIMD_COMMON_SWAPBYTES_HPP_INCLUDED
#define BOOST_SIMD_BITWISE_FUNCTIONS_SIMD_COMMON_SWAPBYTES_HPP_INCLUDED

#include <boost/simd/bitwise/functions/swapbytes.hpp>
#include <boost/simd/include/functions/shuffle.hpp>
#include <boost/simd/include/functions/simd/bitwise_cast.hpp>
#include <boost/dispatch/meta/as_integer.hpp>
#include <boost/simd/sdk/simd/native.hpp>

namespace boost { namespace simd
{
  namespace details
  {
    template<std::size_t N> struct swap_bytes_helper
    {
      template<typename I, typename C>
      struct apply : boost::mpl::int_<N*(I::value/N)+N-1-I::value%N>
      {};
    };
  }
} }

namespace boost { namespace simd { namespace ext
{
  BOOST_DISPATCH_IMPLEMENT( swapbytes_,  tag::simd_
                          , (A0)(X)
                          , ((simd_<arithmetic_<A0>, X>))
                          )
  {
    typedef A0 result_type;
    BOOST_SIMD_FUNCTOR_CALL(1)
    {
      using s0        = typename meta::scalar_of<A0>::type;
      using i8        = typename meta::vector_of<uint8_t, sizeof(A0)>::type;
      using pattern_t = details::swap_bytes_helper<sizeof(s0)>;

      return bitwise_cast<A0>(shuffle<pattern_t>(bitwise_cast<i8>(a0)));
    }
  };
} } }

#endif


text:
#include "stdafx.h"
#include "GameManager.h"
#include "UserSessionManager.h"
#include <boost/thread.hpp>

using namespace boost;

GameManager::GameManager()
{
	m_next_roomId = 0;
}

int GameManager::createGame(CreateRoomRequest *req)
{
	int tableId = m_next_roomId++;
	GameGrailConfig *config = new GameGrailConfig(req->max_player(),
		                                          req->role_strategy(),
												  req->first_extension(),
												  req->second_extension(),
												  req->sp_mo_dao(),
												  req->seat_mode(),
												  req->silence());
	config->setTableName(req->room_name());
	config->setTableId(tableId);
	GameGrail *game = new GameGrail(config);
	m_gameGrailMap.insert(GameMapType::value_type(tableId, game));
	GameContext context;
	context.allowGuest = req->allow_guest();
	context.password = req->password();
	m_gameGrailContextMap.insert(GameContextMapType::value_type(tableId, context));
	thread(gameThread, game);
	delete config;
	return tableId;
}

void GameManager::Check()
{
	for(GameMapType::iterator iter = m_gameGrailMap.begin(); iter != m_gameGrailMap.end(); )
	{
		if(iter->second->dead)
		{
			ztLoggerWrite(ZONE, e_Information, "GameManager::Check: delete game[%d].", iter->first);
			SAFE_DELETE(iter->second);
			m_gameGrailMap.erase(iter++);
			m_gameGrailContextMap.erase(iter->first);
		}
		else{
			iter++;
		}
	}
}

int GameManager::tryEnterRoom(string userId, string nickname, EnterRoomRequest* req, int& playerId, ACCOUNT_STATUS identity)
{
	int roomId = req->room_id();
	GameMapType::iterator iter1 = m_gameGrailMap.find(roomId);
	if(iter1 == m_gameGrailMap.end())
	{
		return GE_INVALID_TABLEID;
	}
	if(!iter1->second->playing)
	{
		GameContextMapType::iterator iter2 = m_gameGrailContextMap.find(roomId);
		if(iter2 != m_gameGrailContextMap.end())
		{
			GameContext context = iter2->second;
			if(!context.allowGuest && identity == STATUS_GUEST)
				return GE_NOT_WELCOME;
			if(!context.password.empty() && req->password() != context.password)
				return GE_WRONG_PASSWORD;
		}
	}
	return enterRoom(userId, nickname, req, playerId);
}

int GameManager::enterRoom(string userId, string nickname, EnterRoomRequest* req, int& playerId)
{
	EnterRoomRequest* request = (EnterRoomRequest*)req;
	int ret;
	int roomId = request->room_id();

	GameMapType::iterator iter = m_gameGrailMap.find(roomId);
	if(iter == m_gameGrailMap.end())
	{
		return GE_INVALID_TABLEID;
	}

	GameGrail *game = iter->second;

	ret = game->playerEnterIntoTable(userId, nickname, playerId);
	if (ret == GE_SUCCESS){
		game->onPlayerEnter(playerId);
		return GE_SUCCESS;
	}

	ret = game->guestEnterIntoTable(userId);
	if (ret == GE_SUCCESS){
		playerId = GUEST;
		game->onGuestEnter(userId);
		return GE_SUCCESS;
	}

	ztLoggerWrite(ZONE, e_Error, "GameManager::enterRoom() userId [%s] cannot enter Table %d. Ret: %d",
		userId.c_str(), request->room_id(), ret);

	return ret;
}

int GameManager::getGame(int tableId, GameGrail** game)
{
	if(tableId < 0)
		return -1;
	GameMapType::iterator iter;

	iter = m_gameGrailMap.find(tableId);
	if(iter == m_gameGrailMap.end())
	{
		return -1;
	}
	else
	{
		*game = iter->second;
	}

	return 0;
}

int GameManager::getGameList(RoomListRequest* req, RoomListResponse* res)
{
	int role_strategy = req->role_strategy();

	for(GameMapType::iterator iter1 = m_gameGrailMap.begin(); iter1 != m_gameGrailMap.end(); iter1++)
	{
		RoomListResponse *response = (RoomListResponse*)res;
		RoomListResponse_RoomInfo *room = response->add_rooms();
		int roomId = iter1->first;
		GameGrail* game = iter1->second;
		room->set_room_id(roomId);
		room->set_room_name(game->getGameName());
		room->set_max_player(game->getGameMaxPlayers());
		room->set_now_player(game->getGameNowPlayers());
		room->set_role_strategy((ROLE_STRATEGY)game->m_roleStrategy);
		room->set_seat_mode((SEAT_MODE)game->m_seatMode);
		room->set_first_extension(game->m_firstExtension);
		room->set_second_extension(game->m_secondExtension);
		room->set_sp_mo_dao(game->m_spMoDao);
		GameContextMapType::iterator iter2 = m_gameGrailContextMap.find(roomId);
		if(iter2 != m_gameGrailContextMap.end())
		{
			GameContext context = iter2->second;
			room->set_allow_guest(context.allowGuest);
			room->set_has_password(!context.password.empty());
		}
		room->set_silence(game->m_silence);
		room->set_playing(game->playing);

	}

	return 0;
}

int GameManager::setPlayerReady(int roomId, int playerId, ReadyForGameRequest* req)
{
	if(playerId == GUEST)
		return 0;
	GameMapType::iterator iter;
	iter = m_gameGrailMap.find(roomId);
	if(iter != m_gameGrailMap.end())
	{
		GameGrail *game = iter->second;
		if(game->topGameState()->state == STATE_WAIT_FOR_ENTER){

			if(req->type() == ReadyForGameRequest_Type_START_READY){
				game->setStartReady(playerId, true);
			}
			else if(req->type() == ReadyForGameRequest_Type_CANCEL_START_REDAY){
				game->setStartReady(playerId, false);
			}
			return 0;
		}
	}
	return -1;
}

void gameThread(Game* game)
{
	game->exec();
}

max_stars_repo_name: chntujia/CodfiyAsteriatedGrailServer

max_issues_repo_name: chntujia/CodfiyAsteriatedGrailServer

max_forks_repo_name: chntujia/CodfiyAsteriatedGrailServer


text:
// Copyright 2019, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt

#include <boost/endian/conversion.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/cstdint.hpp>

namespace N
{

struct X
{
    boost::uint32_t m;
};

template<class T> typename boost::enable_if_<boost::is_same<T, X>::value, T>::type endian_reverse( T x )
{
    using boost::endian::endian_reverse;

    X r = { endian_reverse( x.m ) };
    return r;
}

} // namespace N

int main()
{
    using namespace boost::endian;

    N::X x1 = { 0x01020304 };
    N::X x2 = endian_reverse( x1 );

    BOOST_TEST_EQ( x2.m, 0x04030201 );

    return boost::report_errors();
}

max_issues_repo_name: qingkouwei/mediaones


text:
#ifndef TIMESERIES_H
#define TIMESERIES_H

#include <cmath>
#include <cstring>
#include <iostream>
#include <limits>
#include <string>

#include <boost/serialization/serialization.hpp>

#define INF std::numeric_limits<data_t>::infinity()
#define EPS 1e-9

// EXPERIMENT
extern int extraTimeSeries;

namespace genex {

typedef double data_t;

int calculateWarpingBandSize(int length, double ratio);

/**
 *  @brief header of a time series
 *
 *  A TimeSeries does not holds the actual data of a time series. It only has a pointer
 *  pointing to a part of data in a TimeSeriesSet. It also contains the starting position
 *  and ending position of the time series so that it can represent a sub-sequence.
 *  To be exact, a TimeSeries is a half-closed interval [start, end) of a time series in
 *  a TimeSeriesSet.
 *
 *  Outside the context of TimeSeriesSet. TimeSeries can be used as a general purpose container
 *  by providing a pointer to an array of data and its length.
 */
class TimeSeries
{
public:

  /**
   *  @brief constructor for TimeSeries
   *
   *  @param data a pointer pointing to the actual data
   *  @param index index of this time series in a TimeSeriesSet
   *  @param start starting position of this time series
   *  @param end ending position of this time series
   */
  TimeSeries(data_t *data, int index, int start, int end);

  /**
   *  @brief constructor for TimeSeries
   *
   *  This constructor is use when only data and length is needed
   *  to specify the time series. Index is set to 0, starting position
   *  is set to 0 and ending position is the length of the time series
   *
   *  @param data a pointer pointing to the actual data
   *  @param length length of the time series
   */
  TimeSeries(data_t *data, int length);

  /**
   *  @brief constructor for TimeSeries
   *
   *  This constructor is use when only length is needed
   *  to specify the time series. Index is set to 0, starting position
   *  is set to 0 and ending position is the length of the time series
   *  Memory is allocated for the data.
   *
   *  @param length length of the time series
   */
  TimeSeries(int length);

  /**
   * @brief Copy constructor
   */
  TimeSeries(const TimeSeries& other);

  /**
   *  @brief Copy assignment and move assignment
   */
  TimeSeries& operator=(const TimeSeries& other);
  TimeSeries& operator=(TimeSeries&& other);

  /**
   *  @brief destructor
   */
  ~TimeSeries();

  /**
   *  @brief get a value of this time series
   *
   *  @param idx index of the value in this time series
   *  @return the value at idx
   *
   *  @throw GenexException if the index is out of bound
   */
  data_t& operator[](int idx) const;

  /**
   *  @brief accumulate data from other time series into this one
   *
   *  The data of the given time series is added to this time series
   *  point-wise. The other time series must have the same length as this
   *  one.
   *  @param other the other time series to be added to this one.
   *  @return the reference to this time series
   *
   *  @throw GenexException if the other time series has different length
   *         from this one
   */
  TimeSeries& operator+=(const TimeSeries& other);

  /**
   * @brief compare two time series
   */
  bool operator==(const TimeSeries& other) const;

  /**
   *  @brief gets the length of this time series
   *
   *  @return length of this time series
   */
  int getLength() const { return this->length; }

  /**
   *  @brief gets the index of the data
   *
   *  @return the index of the data from its timeseries
   */
  int getIndex() const { return this->index; }

  /**
   *  @brief gets the start of the data
   *
   *  @return the start of the data from its timeseries
   */
  int getStart() const { return this->start; }

  /**
   *  @brief gets the end of the data
   *
   *  @return the end of the data from its timeseries
   */
  int getEnd() const { return this->end; }

  /**
   *  @brief returns the average of the whole time series
   */
  data_t average();

  const data_t* getKeoghLower(int warpingBand) const;
  const data_t* getKeoghUpper(int warpingBand) const;

  const data_t* getData() const;
  std::string getIdentifierString() const;

  friend std::ostream& operator<<(std::ostream&, const TimeSeries&);

private:
  // ATTENTION: Always offset by 'start' when indexing 'data' (i.e. data[start + i])
  data_t* data = nullptr;
  bool isOwnerOfData;
  int index;
  int start;
  int end;
  int length;

  mutable bool keoghCacheValid = false;
  mutable data_t* keoghLower = nullptr;
  mutable data_t* keoghUpper = nullptr;
  mutable double cachedWarpingBand;

  std::ostream &printData(std::ostream &out) const;

  /**
   * @brief generates the upper and lower envelope used in Keogh lower bound calculation
   * @param bandSize size of the Sakoe-Chiba warpping band
   */
  void generateKeoghLU(int warpingBand) const;

  /*************************
   *  Start serialization
   *************************/
  friend class boost::serialization::access;

  template <class A>
  void serialize(A &ar, unsigned) {
    for (int i = 0; i < this->length; i++) {
      ar & data[this->start + i];
    }
  }
  /*************************
   *  End serialization
   *************************/
};

/* For printing */
inline std::ostream &operator<<(std::ostream &os, const TimeSeries &ts) {
    return ts.printData(os);
}

/**
 *  @brief a struct pairing a dist with a time series
 *
 */
struct candidate_time_series_t
{
  TimeSeries data;
  data_t dist;

  bool operator<(const candidate_time_series_t& rhs) const
  {
    if (std::abs(dist - rhs.dist) < EPS)
    {
      if (data.getIndex() == rhs.data.getIndex())
      {
        if (data.getStart() == rhs.data.getStart())
        {
          return data.getLength() < rhs.data.getLength();
        }
        return data.getStart() < rhs.data.getStart();
      }
      return data.getIndex() < rhs.data.getIndex();
    }
    return dist < rhs.dist;
  }
  candidate_time_series_t(const TimeSeries& data, data_t dist) : data(data), dist(dist) {};
  candidate_time_series_t() : data(0), dist(0) {}

  bool operator==(const candidate_time_series_t& rhs) const
  {
    return data == rhs.data && std::abs(dist - rhs.dist) < EPS;
  }
};

} // namespace genex

#endif // TIMESERIES_H

max_stars_repo_name: mihinsumaria/genex

max_issues_repo_name: mihinsumaria/genex

max_forks_repo_name: mihinsumaria/genex


text:
// Boost.Range library concept checks
//
//  Copyright Daniel Walker 2006. Use, modification and distribution
//  are subject to the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_CONCEPTS_HPP
#define BOOST_RANGE_CONCEPTS_HPP

#include <boost/concept_check.hpp>
#include <boost/iterator/iterator_concepts.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/metafunctions.hpp>

/*!
 * \file
 * \brief Concept checks for the Boost Range library.
 *
 * The structures in this file may be used in conjunction with the
 * Boost Concept Check library to insure that the type of a function
 * parameter is compatible with a range concept. If not, a meaningful
 * compile time error is generated. Checks are provided for the range
 * concepts related to iterator traversal categories. For example, the
 * following line checks that the type T models the ForwardRange
 * concept.
 *
 * \code
 * function_requires<ForwardRangeConcept<T> >();
 * \endcode
 *
 * An additional concept check is required for the value access
 * property of the range. For example to check for a
 * ForwardReadableRange, the following code is required.
 *
 * \code
 * function_requires<ForwardRangeConcept<T> >();
 * function_requires<
 *     ReadableIteratorConcept<
 *         typename range_iterator<T>::type
 *     >
 * >();
 * \endcode
 *
 * \see http://www.boost.org/libs/range/doc/range.html for details
 * about range concepts.
 * \see http://www.boost.org/libs/iterator/doc/iterator_concepts.html
 * for details about iterator concepts.
 * \see http://www.boost.org/libs/concept_check/concept_check.htm for
 * details about concept checks.
 */

namespace boost {

    //! Check if a type T models the SinglePassRange range concept.
    template<typename T>
    struct SinglePassRangeConcept {
        typedef typename range_value<T>::type range_value;
        typedef typename range_iterator<T>::type range_iterator;
        typedef typename range_const_iterator<T>::type range_const_iterator;
        void constraints()
        {
            function_requires<
                boost_concepts::SinglePassIteratorConcept<
                    range_iterator
                >
            >();
            i = boost::begin(a);
            i = boost::end(a);
            b = boost::empty(a);
            const_constraints(a);
        }
        void const_constraints(const T& a)
        {
            ci = boost::begin(a);
            ci = boost::end(a);
        }
        T a;
        range_iterator i;
        range_const_iterator ci;
        bool b;
    };

    //! Check if a type T models the ForwardRange range concept.
    template<typename T>
    struct ForwardRangeConcept {
        typedef typename range_difference<T>::type range_difference;
        typedef typename range_size<T>::type range_size;
        void constraints()
        {
            function_requires<
                SinglePassRangeConcept<T>
            >();
            function_requires<
                boost_concepts::ForwardTraversalConcept<
                    typename range_iterator<T>::type
                >
            >();
            s = boost::size(a);
        }
        T a;
        range_size s;
    };

    //! Check if a type T models the BidirectionalRange range concept.
    template<typename T>
    struct BidirectionalRangeConcept {
        typedef typename range_reverse_iterator<T>::type range_reverse_iterator;
        typedef typename range_const_reverse_iterator<T>::type range_const_reverse_iterator;
        void constraints()
        {
            function_requires<
                    ForwardRangeConcept<T>
            >();
            function_requires<
                boost_concepts::BidirectionalTraversalConcept<
                    typename range_iterator<T>::type
                >
            >();
            i = boost::rbegin(a);
            i = boost::rend(a);
            const_constraints(a);
            }
        void const_constraints(const T& a)
        {
            ci = boost::rbegin(a);
            ci = boost::rend(a);
        }
        T a;
        range_reverse_iterator i;
        range_const_reverse_iterator ci;
    };

    //! Check if a type T models the RandomAccessRange range concept.
    template<typename T>
    struct RandomAccessRangeConcept {
        void constraints()
        {
            function_requires<
                BidirectionalRangeConcept<T>
            >();
            function_requires<
                boost_concepts::RandomAccessTraversalConcept<
                    typename range_iterator<T>::type
                >
            >();
            }
    };

} // namespace boost

#endif // BOOST_RANGE_CONCEPTS_HPP

max_stars_repo_name: dstrigl/mcotf

max_issues_repo_name: dstrigl/mcotf

max_forks_repo_name: dstrigl/mcotf


text:
/********************************************************/
/*                Laurent Hébert-Dufresne               */
/* Age of edges or nodes by OD of an undirected network */
/* 			     based on arXiv:1510.08542              */
/*                   Santa Fe Institute                 */
/********************************************************/
#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <stdio.h>
#include <time.h>
#include <set>
//#include <boost/filesystem/operations.hpp>
//#include <boost/filesystem/fstream.hpp>
//#include <boost/filesystem/path.hpp>
using namespace std;

//COMPARISON (to order set of [node tag,degree] object by degree
struct classcomp {
  bool operator() (const pair<int,int>& lhs, const pair<int,int>& rhs) const
  {return lhs.second<rhs.second;}
};

//COMPARISON (to order set of [node tag,degree] object by degree
struct classcomp2 {
  bool operator() (const pair< pair<int,int> ,int>& lhs, const pair< pair<int,int> ,int>& rhs) const
  {return lhs.second<rhs.second;}
};

//GLOBAL VARIABLES DEFINITION
vector< vector<int> > adjmat; //[neighbours]
vector<int> degree; //[degree]
multiset< pair<int,int>, classcomp> tags; //[tag,degree]
multiset< pair<int,int> > edges; //[node1, node2]
multiset< pair< pair<int,int> ,int>, classcomp2> ranked_edges; //[tag,degree]

//MAIN
int main(int argc, const char *argv[])
{
  //NETWORK
  std::string name = argv[1]; //path to edgelist
  int nodes = 0;
  if(argc>2) nodes = atoi(argv[2]); //rank output for: 0==edges, 1==nodes

//INPUT AND CONSTRUCTION OF STRUCTURES
//PREPARES INPUT & OUTPUT
std::ifstream input(name.c_str());
string line;
ifstream input0(name.c_str());
int temp = 0;
int MAX = 0;
int node1;
int node2;
if (!input0.is_open()) {
	cerr<<"error in filenames of input directory!"<<endl;;
 	return EXIT_FAILURE;
} //end if
else {
	while ( input0 >> temp ) if(temp > MAX) MAX = temp;
}
MAX = MAX+1;
int link=0;
//cout << "Number of nodes: " << MAX << endl;
adjmat.resize(MAX);
degree.resize(MAX);
if (!input.is_open()) {
	cerr<<"error in filenames of input directory!"<<endl;;
 	return EXIT_FAILURE;
} //end if
else {
    string line_buffer;
    while (getline(input, line_buffer))
    {
      	stringstream ls(line_buffer);
      	ls >> node1;
      	ls >> node2;
	// while ( input >> node1 >> std::ws >> node2 >> std::ws >> tmp >> std::ws ) {
		//if(find(adjmat[node1].begin(),adjmat[node1].end(),node2)==adjmat[node1].end() && node1 != node2) {
		adjmat[node1].push_back(node2);
		adjmat[node2].push_back(node1);
		edges.insert(make_pair(node1,node2));
		++degree[node1];
		++degree[node2];
		link = link+2;
		//}
	} //end while
} //end else
input.close();
for(int el=0; el<MAX; ++el) tags.insert(make_pair(el,degree[el]));

vector<int> realindegree = degree;

//ALGORITHM
vector<int> core(MAX,-1);
vector<int> pass(MAX,-1);
vector<int> age(MAX,-1);
multiset< pair<int,int>, classcomp>::iterator v;
multiset< pair<int,int>, classcomp>::iterator it1;
multiset< pair<int,int>, classcomp>::iterator it2;
pair<multiset< pair<int,int>, classcomp>::iterator,multiset< pair<int,int>, classcomp>::iterator> ret_intern;
pair<multiset< pair<int,int>, classcomp>::iterator,multiset< pair<int,int>, classcomp>::iterator> ret_pass;
int source;
int newguy;
int neighbour;
int currentpass=1;
v = tags.begin();
int maxcore = 0; int t=0;
while(tags.size()>0) {
	newguy = (*v).first;
	if(degree[newguy]>maxcore) maxcore = degree[newguy];//keeping track of the number of cores
	ret_pass = tags.equal_range(make_pair(0,degree[newguy]));//all nodes in the next layer
	int number = tags.count(make_pair(0,degree[newguy]));//number of nodes in next layer
	it1=ret_pass.first;
	for(int tmp=0; tmp<number; ++tmp,++it1) {//loops around everyone in the same layer
		source = (*it1).first; //node in the layer
		core[source] = degree[source]; //core for that node
		pass[source] = currentpass; //layer for that node
		age[source] = t;
		for(int u=0; u<adjmat[source].size(); ++u) {
			neighbour = adjmat[source][u];
			if(degree[neighbour] > degree[source]) {
				ret_intern = tags.equal_range(make_pair(neighbour,degree[neighbour]));
				for(it2=ret_intern.first; it2!=ret_intern.second; ++it2) {
					if((*it2).first==neighbour) {
						tags.erase(it2);
						break;
					}
				}
				--degree[neighbour];
				tags.insert(make_pair(neighbour,degree[neighbour]));
			}
		}
	}
	t+=number;
	it1=ret_pass.first;
	for(int tmp=0; tmp<number; ++tmp,++it1) tags.erase(it1);
	v = tags.begin(); ++currentpass;
}

if(nodes==0) {//output edges

	for(multiset< pair<int,int> >::iterator e = edges.begin(); e!=edges.end(); ++e) {
		int age0=t-age[(*e).first];
		if(t-age[(*e).second]>age0) age0=t-age[(*e).second];
		ranked_edges.insert(make_pair((*e),age0));
	}

	int time = 0;
 	int	class_id = 0;
 	int class_base_time = 0;
	multiset< pair<int,int> > class_content;

	for(multiset< pair< pair<int,int>,int> >::iterator e = ranked_edges.begin(); e!=ranked_edges.end(); ++e) {
		if (e->second != class_id)
		{
			pair<int,int> last_out_edge = make_pair(class_content.begin()->first, class_content.begin()->second);
			int out_edge_tag = -1;
			for (multiset< pair<int,int> >::iterator e2 = class_content.begin(); e2 != class_content.end(); ++e2)
			{
				if (e2->first == last_out_edge.first && e2->second == last_out_edge.second)
				{
					++out_edge_tag;
				}
				else
				{
					out_edge_tag = 0;
					last_out_edge = make_pair(e2->first, e2->second);
				}
				cout << e2->first << " " << e2->second << " " << out_edge_tag << " " << class_base_time + float(class_content.size() + 1)/2 -1 << "\n";
			}
			class_content.clear();
			class_id = (*e).second;
			class_base_time = time;
		}
		class_content.insert(e->first);
		++time;
	}
	pair<int,int> last_out_edge = make_pair(class_content.begin()->first, class_content.begin()->second);
	int out_edge_tag = -1;
	for (multiset< pair<int,int> >::iterator e2 = class_content.begin(); e2 != class_content.end(); ++e2)
	{
		if (e2->first == last_out_edge.first && e2->second == last_out_edge.second)
		{
			++out_edge_tag;
		}
		else
		{
			out_edge_tag = 0;
			last_out_edge = make_pair(e2->first, e2->second);
		}
		cout << e2->first << " " << e2->second << " " << out_edge_tag << " " << class_base_time + float(class_content.size() + 1)/2 -1 << "\n";
	}
}
else {//output nodes

	for(int dummy=0; dummy<core.size(); ++dummy) cout << dummy << " " << pass[dummy] << "\n";

}

return 0;
} //end main

max_stars_repo_name: junipertcy/network-archaeology

max_issues_repo_name: junipertcy/network-archaeology

max_forks_repo_name: junipertcy/network-archaeology


text:
/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

#include "precompiled_sc.hxx"

#include "ScPanelFactory.hxx"

#include <AlignmentPropertyPanel.hxx>
#include <CellAppearancePropertyPanel.hxx>
#include <NumberFormatPropertyPanel.hxx>
#include <navipi.hxx>
#include <dwfunctr.hxx>
#include "sc.hrc"

#include <sfx2/sidebar/SidebarPanelBase.hxx>
#include <sfx2/sfxbasecontroller.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/window.hxx>
#include <rtl/ref.hxx>
#include <comphelper/namedvaluecollection.hxx>

#include <boost/bind.hpp>

using namespace css;
using namespace cssu;
using ::rtl::OUString;

namespace sc { namespace sidebar {

#define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
#define IMPLEMENTATION_NAME "org.apache.openoffice.comp.sc.sidebar.ScPanelFactory"
#define SERVICE_NAME "com.sun.star.ui.UIElementFactory"

::rtl::OUString SAL_CALL ScPanelFactory::getImplementationName (void)
{
    return A2S(IMPLEMENTATION_NAME);
}

cssu::Reference<cssu::XInterface> SAL_CALL ScPanelFactory::createInstance(
    const uno::Reference<lang::XMultiServiceFactory>& )
{
    ::rtl::Reference<ScPanelFactory> pPanelFactory (new ScPanelFactory());
    cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pPanelFactory.get()), cssu::UNO_QUERY);
    return xService;
}

cssu::Sequence<OUString> SAL_CALL ScPanelFactory::getSupportedServiceNames (void)
{
    cssu::Sequence<OUString> aServiceNames (1);
    aServiceNames[0] = A2S(SERVICE_NAME);
    return aServiceNames;

}

ScPanelFactory::ScPanelFactory (void)
    : PanelFactoryInterfaceBase(m_aMutex)
{
}

ScPanelFactory::~ScPanelFactory (void)
{
}

Reference<ui::XUIElement> SAL_CALL ScPanelFactory::createUIElement (
    const ::rtl::OUString& rsResourceURL,
    const ::cssu::Sequence<css::beans::PropertyValue>& rArguments)
    throw(
        container::NoSuchElementException,
        lang::IllegalArgumentException,
        RuntimeException)
{
    Reference<ui::XUIElement> xElement;

    const ::comphelper::NamedValueCollection aArguments (rArguments);
    Reference<frame::XFrame> xFrame (aArguments.getOrDefault("Frame", Reference<frame::XFrame>()));
    Reference<awt::XWindow> xParentWindow (aArguments.getOrDefault("ParentWindow", Reference<awt::XWindow>()));
    const sal_uInt64 nBindingsValue (aArguments.getOrDefault("SfxBindings", sal_uInt64(0)));
    SfxBindings* pBindings = reinterpret_cast<SfxBindings*>(nBindingsValue);

    ::Window* pParentWindow = VCLUnoHelper::GetWindow(xParentWindow);
    if ( ! xParentWindow.is() || pParentWindow==NULL)
        throw RuntimeException(
            A2S("PanelFactory::createUIElement called without ParentWindow"),
            NULL);
    if ( ! xFrame.is())
        throw RuntimeException(
            A2S("PanelFactory::createUIElement called without Frame"),
            NULL);
    if (pBindings == NULL)
        throw RuntimeException(
            A2S("PanelFactory::createUIElement called without SfxBindings"),
            NULL);

#define DoesResourceEndWith(s) rsResourceURL.endsWithAsciiL(s,strlen(s))
    if (DoesResourceEndWith("/AlignmentPropertyPanel"))
    {
        AlignmentPropertyPanel* pPanel = AlignmentPropertyPanel::Create( pParentWindow, xFrame, pBindings );
        xElement = sfx2::sidebar::SidebarPanelBase::Create(
            rsResourceURL,
            xFrame,
            pPanel,
            ui::LayoutSize(-1,-1,-1));
    }
    else if (DoesResourceEndWith("/CellAppearancePropertyPanel"))
    {
        CellAppearancePropertyPanel* pPanel = CellAppearancePropertyPanel::Create( pParentWindow, xFrame, pBindings );
        xElement = sfx2::sidebar::SidebarPanelBase::Create(
            rsResourceURL,
            xFrame,
            pPanel,
            ui::LayoutSize(-1,-1,-1));
    }
    else if (DoesResourceEndWith("/NumberFormatPropertyPanel"))
    {
        NumberFormatPropertyPanel* pPanel = NumberFormatPropertyPanel::Create( pParentWindow, xFrame, pBindings );
        xElement = sfx2::sidebar::SidebarPanelBase::Create(
            rsResourceURL,
            xFrame,
            pPanel,
            ui::LayoutSize(-1,-1,-1));
    }
    else if (DoesResourceEndWith("/NavigatorPanel"))
    {
        Window* pPanel = new ScNavigatorDlg(pBindings, NULL, pParentWindow, false);
        xElement = sfx2::sidebar::SidebarPanelBase::Create(
            rsResourceURL,
            xFrame,
            pPanel,
            ui::LayoutSize(0,-1,-1));
    }
    else if (DoesResourceEndWith("/FunctionsPanel"))
    {
        Window* pPanel = new ScFunctionDockWin(pBindings, NULL, pParentWindow, ScResId(FID_FUNCTION_BOX));
        xElement = sfx2::sidebar::SidebarPanelBase::Create(
            rsResourceURL,
            xFrame,
            pPanel,
            ui::LayoutSize(0,-1,-1));
    }
#undef DoesResourceEndWith

    return xElement;
}

} } // end of namespace sc::sidebar

// eof

ext: cxx

max_stars_repo_name: Grosskopf/openoffice

max_issues_repo_name: Grosskopf/openoffice

max_forks_repo_name: Grosskopf/openoffice