<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "comm_struct.h"
#include "comm_const.h"
#include "version.h"

extern int press_rate;
extern double press_interval;
extern host_info host;
extern int press_time;

//如何使用本工具
void usage(const char* tool_name)
{
	fprintf( stderr, "usage:  %s\n", tool_name );
	fprintf( stderr, "        -r [or --rate] N                 [REQUIRED] specify the press rate (unit: query per second).\n" );
	fprintf( stderr, "        -t [or --time] N                 [REQUIRED] test time (unit: second). \n" );
	fprintf( stderr, "        -h [or --host] XXX.XXX.XXX.XXX   target host ip. The default host ip is 127.0.0.1 .\n" );
	fprintf( stderr, "        -p [or --port] N                 port number. The default port number is 80.\n" );
	fprintf( stderr, "        -u [or --uri ] /index.html       uri of the request.\n");
	exit(1);
}

//打印读取的参数信息
void print_info(void)
{
	fprintf( stdout, "\n");
	fprintf( stdout, "This is %s (last updated on %s), an HTTP benchmarking tool.\n", VERSION, LAST_UPDATE);
	fprintf( stdout, "Copyright © 2014 %s. Email: %s\n\n", AUTHOR, CONTACT);
	fprintf( stdout, "Test Information\n");
	fprintf( stdout, "    Host       : %s\n", host.host_ip );
	fprintf( stdout, "    Port       : %d\n", host.port );
	fprintf( stdout, "    Uri        : %s\n", host.uri);
	fprintf( stdout, "    Target QPS : %d\n", press_rate );
	fprintf( stdout, "    Test Time  : %d\n", press_time);
	fprintf( stdout, "\n");
	return;
}

void check_setting(void)
{
	if(press_rate <= 0 || press_rate >= MAX_RATE){
		fprintf(stderr, "The press rate is illegal. The request rate should be between 1 and %d QPS.\n", MAX_RATE);
		exit(1);
	}

	if(press_time <= 0 || press_time > MAX_TIME){
		fprintf(stderr, "The press time is too long! The test time should be between 1 and %d seconds.\n", MAX_TIME);
		exit(1);
	}

	return ;
}

void statistics_calculation(final_statistics *overall_stat, const request_data test_data[], const int press_number)
{
	unsigned int min_connect_time=UINT_MAX;
	unsigned int max_connect_time=0;
	double avg_connect_time=0.0;

	unsigned int min_response_time = UINT_MAX;
	unsigned int max_response_time = 0;
	double avg_response_time = 0.0;

	unsigned int min_request_time = UINT_MAX;
	unsigned int max_request_time = 0;
	double avg_request_time = 0;

	int connect_count = 0; //实时统计请求连接的成功数
	int response_count = 0; //实时统计成功收到回复的连接数
	for(int i=0; i<press_number; i++)
	{
		if(test_data[i].is_connected){ //如果该请求连接成功
			connect_count ++;
			if(test_data[i].connect_time > max_connect_time){
				max_connect_time = test_data[i].connect_time;
			}
			if (test_data[i].connect_time < min_connect_time){
				min_connect_time = test_data[i].connect_time;
			}
			avg_connect_time = 1.0*(connect_count-1)/connect_count*avg_connect_time + 1.0/connect_count*test_data[i].connect_time;
		}

		if(test_data[i].is_replied && test_data[i].is_connected){ //如果该请求连接成功，发送出去后也成功收到回复
			response_count ++;
			overall_stat->total_byte += test_data[i].byte_transfered;

			int response_time_elapsed = test_data[i].recv_finish_time - test_data[i].start_send_time;
			if(response_time_elapsed > max_response_time){
				max_response_time = response_time_elapsed;
			}
			if(response_time_elapsed < min_response_time){
				min_response_time = response_time_elapsed;
			}
			avg_response_time = 1.0*(response_count -1)/response_count*avg_response_time + 1.0/response_count*response_time_elapsed;

			if(test_data[i].recv_finish_time > max_request_time){
				max_request_time = test_data[i].recv_finish_time;
			}
			if(test_data[i].recv_finish_time < min_request_time){
				min_request_time = test_data[i].recv_finish_time;
			}
			avg_request_time = 1.0*(response_count - 1)/response_count*avg_request_time + 1.0/response_count*test_data[i].recv_finish_time;
		}

		if((!test_data[i].is_replied) && test_data[i].is_connected){
			overall_stat->response_fail_count ++;
		}
	}

	overall_stat->avg_connect_time = (unsigned int)avg_connect_time;
	overall_stat->min_connect_time = min_connect_time;
	overall_stat->max_connect_time = max_connect_time;

	overall_stat->avg_response_time =(unsigned int)avg_response_time;
	overall_stat->min_response_time = min_response_time;
	overall_stat->max_response_time = max_response_time;

	overall_stat->avg_request_time = (unsigned int)avg_request_time;
	overall_stat->min_request_time = min_request_time;
	overall_stat->max_request_time = max_request_time;

	overall_stat->connect_fail_count = press_number - connect_count;

	overall_stat->total_fail_count = overall_stat->response_fail_count + overall_stat->connect_fail_count;
	overall_stat->total_request = press_number;
	overall_stat->fail_percent = 1.0*overall_stat->total_fail_count / overall_stat->total_request;
}

void print_statistics(final_statistics *overall_stat)
{
	fprintf(stdout, "    TCP Connect Fail Count:   %-9d%-8s\n", overall_stat->connect_fail_count, "[#]");
	fprintf(stdout, "    HTTP Response Fail Count: %-9d%-8s\n", overall_stat->response_fail_count, "[#]");
	fprintf(stdout, "    Overall Fail Count:       %-9d%-8s\n", overall_stat->total_fail_count, "[#]");
	fprintf(stdout, "    Total Request Number:     %-9d%-8s\n", overall_stat->total_request, "[#]");
	fprintf(stdout, "    Fail Percent:             %.3f%%\n", 100*(overall_stat->fail_percent));
	fprintf(stdout, "    Total Bytes Transferred:  %-9lu%-8s\n", overall_stat->total_byte, "[Bytes]");
	fprintf(stdout, "\n");
	fprintf(stdout, "Request Time [unit: us]\n");
	fprintf(stdout, "                             min         max         avg\n");
	fprintf(stdout, "    TCP Connect Time:  %9u%12u%12u\n", overall_stat->min_connect_time,
		overall_stat->max_connect_time, overall_stat->avg_connect_time);

	fprintf(stdout, "    HTTP Response Time:%9u%12u%12u\n", overall_stat->min_response_time,
		overall_stat->max_response_time, overall_stat->avg_response_time);

	fprintf(stdout, "    Total Request Time:%9u%12u%12u\n", overall_stat->min_request_time,
		overall_stat->max_request_time, overall_stat->avg_request_time);

	return ;
}
<commit_msg>Update output.cpp<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#include "common_struct.h"
#include "common_constant.h"
#include "version.h"

extern int press_rate;
extern double press_interval;
extern host_info host;
extern int press_time;

//如何使用本工具
void usage( const char* tool_name )
{
	fprintf( stderr, "usage:  %s\n", tool_name );
	fprintf( stderr, "        -r [or --rate] N                 [REQUIRED] specify the press rate (unit: query per second).\n" );
	fprintf( stderr, "        -t [or --time] N                 [REQUIRED] test time (unit: second). \n" );
	fprintf( stderr, "        -h [or --host] XXX.XXX.XXX.XXX   target host ip. The default host ip is 127.0.0.1 .\n" );
	fprintf( stderr, "        -p [or --port] N                 port number. The default port number is 80.\n" );
	fprintf( stderr, "        -u [or --uri ] /index.html       uri of the request.\n" );
	exit( 1 );
}

//打印读取的参数信息
void print_info( void )
{
	fprintf( stdout, "\n" );
	fprintf( stdout, "This is %s (last updated on %s), an HTTP benchmarking tool.\n", VERSION, LAST_UPDATE );
	fprintf( stdout, "Copyright © 2014 %s. Email: %s\n\n", AUTHOR, CONTACT );
	fprintf( stdout, "Test Information\n" );
	fprintf( stdout, "    Host       : %s\n", host.host_ip );
	fprintf( stdout, "    Port       : %d\n", host.port );
	fprintf( stdout, "    URI        : %s\n", host.uri );
	fprintf( stdout, "    Target QPS : %-6d%-11s\n", press_rate, "[#/second]" );
	fprintf( stdout, "    Test Time  : %-6d%-11s\n", press_time, "[second]" );
	fprintf( stdout, "\n" );
	return;
}

void check_setting( void )
{
	if( press_rate <= 0 || press_rate > MAX_RATE )
	{
		fprintf( stderr, "The press rate is illegal. The request rate should be between 1 and %d RPS.\n", MAX_RATE );
		exit( 1 );
	}

	if( press_time <= 0 || press_time > MAX_TIME )
	{
		fprintf( stderr, "The press time is too long! The test time should be between 1 and %d seconds.\n", MAX_TIME );
		exit( 1 );
	}

	return ;
}

void statistics_calculation( final_statistics *overall_stat, const request_data test_data[], const int press_number )
{
	unsigned int min_connect_time = UINT_MAX;
	unsigned int max_connect_time = 0;
	double avg_connect_time = 0.0;

	unsigned int min_response_time = UINT_MAX;
	unsigned int max_response_time = 0;
	double avg_response_time = 0.0;

	unsigned int min_request_time = UINT_MAX;
	unsigned int max_request_time = 0;
	double avg_request_time = 0;

	int connect_count = 0; //实时统计请求连接的成功数
	int response_count = 0; //实时统计成功收到回复的连接数
	for( int i = 0; i < press_number; i++ )
	{
		if( test_data[i].is_connected == 1 )
		{ //如果该请求连接成功
			connect_count++;
			if( test_data[i].connect_time > max_connect_time )
			{
				max_connect_time = test_data[i].connect_time;
			}
			if ( test_data[i].connect_time < min_connect_time )
			{
				min_connect_time = test_data[i].connect_time;
			}
			avg_connect_time = 1.0 * ( connect_count - 1 ) / connect_count * avg_connect_time + 1.0 / connect_count * test_data[i].connect_time;
		}

		if( test_data[i].is_replied == 1 && test_data[i].is_connected == 1 )
		{ //如果该请求连接成功，发送出去后也成功收到回复
			response_count++;
			overall_stat->total_byte += test_data[i].byte_transfered;

			int response_time_elapsed = test_data[i].recv_finish_time - test_data[i].start_send_time;
			if( response_time_elapsed > max_response_time )
			{
				max_response_time = response_time_elapsed;
			}
			if( response_time_elapsed < min_response_time )
			{
				min_response_time = response_time_elapsed;
			}
			avg_response_time = 1.0 * ( response_count - 1 ) / response_count * avg_response_time + 1.0 / response_count * response_time_elapsed;

			if( test_data[i].recv_finish_time > max_request_time )
			{
				max_request_time = test_data[i].recv_finish_time;
			}
			if( test_data[i].recv_finish_time < min_request_time )
			{
				min_request_time = test_data[i].recv_finish_time;
			}
			avg_request_time = 1.0 * ( response_count - 1 ) / response_count * avg_request_time + 1.0 / response_count * test_data[i].recv_finish_time;
		}

		if( test_data[i].is_replied != 1 && test_data[i].is_connected == 1 )
		{
			overall_stat->response_fail_count++;
		}
	}

	overall_stat->avg_connect_time = (unsigned int)avg_connect_time;
	overall_stat->min_connect_time = min_connect_time;
	overall_stat->max_connect_time = max_connect_time;

	overall_stat->avg_response_time = (unsigned int)avg_response_time;
	overall_stat->min_response_time = min_response_time;
	overall_stat->max_response_time = max_response_time;

	overall_stat->avg_request_time = (unsigned int)avg_request_time;
	overall_stat->min_request_time = min_request_time;
	overall_stat->max_request_time = max_request_time;

	overall_stat->connect_fail_count = press_number - connect_count;

	overall_stat->total_fail_count = overall_stat->response_fail_count + overall_stat->connect_fail_count;
	overall_stat->total_request = press_number;
	overall_stat->fail_percent = 1.0 * overall_stat->total_fail_count / overall_stat->total_request;
}

void print_statistics( final_statistics *overall_stat )
{
	fprintf( stdout, "    TCP Connect Fail Count:   %-9d%-8s\n", overall_stat->connect_fail_count, "[#]" );
	fprintf( stdout, "    HTTP Response Fail Count: %-9d%-8s\n", overall_stat->response_fail_count, "[#]" );
	fprintf( stdout, "    Overall Fail Count:       %-9d%-8s\n", overall_stat->total_fail_count, "[#]" );
	fprintf( stdout, "    Total Request Number:     %-9d%-8s\n", overall_stat->total_request, "[#]" );
	fprintf( stdout, "    Fail Percent:             %.3f%%\n", 100*(overall_stat->fail_percent) );
	fprintf( stdout, "    Total Bytes Transferred:  %-9lu%-8s\n", overall_stat->total_byte, "[Bytes]" );
	fprintf( stdout, "\n" );
	fprintf( stdout, "Request Time [unit: us]\n" );
	fprintf( stdout, "                             min         max         avg\n" );
	fprintf( stdout, "    TCP Connect Time:  %9u%12u%12u\n", overall_stat->min_connect_time,
		overall_stat->max_connect_time, overall_stat->avg_connect_time );

	fprintf( stdout, "    HTTP Response Time:%9u%12u%12u\n", overall_stat->min_response_time,
		overall_stat->max_response_time, overall_stat->avg_response_time );

	fprintf( stdout, "    Total Request Time:%9u%12u%12u\n", overall_stat->min_request_time,
		overall_stat->max_request_time, overall_stat->avg_request_time );
	fprintf( stdout, "\n" );

	return ;
}
<|endoftext|>


<commit_before>#include "AudioRecorder.h"

#include <Tools/ThreadUtil.h>
#include "Tools/NaoTime.h"

#include <chrono>
#include <pulse/error.h>

using namespace std;

namespace naoth
{
  AudioRecorder::AudioRecorder()
    :
    audioReadBuffer(BUFFER_SIZE_RX, 0),
    recordingTimestamp(0),
    capture(false),
    running(false),
    initialized(false),
    resetting(false),
    deinitCyclesCounter(0)
  {
    std::cout << "[INFO] AudioRecorder thread started" << std::endl;
    audioRecorderThread = std::thread([this] {this->execute();});
    ThreadUtil::setPriority(audioRecorderThread, ThreadUtil::Priority::lowest);

    //The following parameters are used by bhuman:
    //TODO implement them as controll in AudioData Representation
    /*
    (unsigned)(10) retries,      // Number of tries to open device.
      (unsigned)(500) retryDelay,  //< Delay before a retry to open device.
      (bool)(false) allChannels,   //< Use all 4 channels, instead of only two
      (unsigned)(8000) sampleRate, //< Sample rate to capture. This variable will contain the framerate the driver finally selected.
      (unsigned)(5000) maxFrames,  //< Maximum number of frames read in one cycle.
      (bool)(true) onlySoundInSet, // If true, the module will not provide audio data in game states other than set

    */
  }

  AudioRecorder::~AudioRecorder()
  {
    running = false;

    if(audioRecorderThread.joinable()) {
      audioRecorderThread.join();
    }

    if(initialized) {
      deinitAudio();
    }
  }

  void AudioRecorder::execute()
  {
    running = true;

    // return;
    while(running)
    {
      int error = 0;

      if(!initialized)
      {
        if(!resetting && capture)
        {
          std::cout << "[AudioRecorder] start recording" << std::endl;
          initAudio();
        }
        else if(resetting)
        {
          usleep(128);
        }
      }
      else
      {
        if(!capture)
        {
          // deinit audio device ~8 seconds after switch off command was set
          // (recording has blocking behaviour 1024 samples equal 128 ms 63*128 equals ~8s
          if(deinitCyclesCounter >= 63)
          {
            std::cout << "stop recording" << std::endl;
            deinitAudio();
            deinitCyclesCounter = 0;
            usleep(128);
            continue;
          }
          deinitCyclesCounter++;
        }
      }

      if(!resetting && initialized)
      {
        //calculate amount of samples needed
        int samplesToRead = SAMPLE_NEW_COUNT * numChannels;
        int bytesToRead = samplesToRead * static_cast<int>(sizeof(short));

        // Record some data
        if (!paSimple || paSimple == NULL)
        {
          std::cerr << "[PulseAudio] pa_simple == NULL" << std::endl;
          running = false;
        }
        //std::cout << "[AudioRecorder] bytesToRead: " << bytesToRead << std::endl;
        if (pa_simple_read(paSimple, &audioReadBuffer[0], bytesToRead, &error) < 0)
        {
          std::cerr << "[PulseAudio] pa_simple_read() failed: " << pa_strerror(error) << std::endl;
          running = false;
        } else {
          recordingTimestamp = NaoTime::getNaoTimeInMilliSeconds();
        }
      }
      else
      {
        usleep(128);
        continue;
      }
    } // end while
  } // end execute

  void AudioRecorder::set(const naoth::AudioControl& controlData)
  {
    std::unique_lock<std::mutex> lock(setMutex, std::try_to_lock);
    if ( lock.owns_lock() )
    {
      if(capture != controlData.capture) {
        capture = controlData.capture;
        std::cout << "Capture: " << capture << std::endl;
      }

      if(activeChannels != controlData.activeChannels)
      {
        resetting =  true;
        if(initialized) {
          deinitAudio();
        }

        //clearBuffers(); //TODO are there any buffers to clear?
        activeChannels = controlData.activeChannels;
        numChannels = controlData.numChannels;
        sampleRate = controlData.sampleRate;
        buffer_size = controlData.buffer_size;
        resetting = false;
      }
    }
  }

  void AudioRecorder::get(AudioData& data)
  {
    if (initialized)
    {
      std::unique_lock<std::mutex> lock(getMutex, std::try_to_lock);
      if ( lock.owns_lock() && recordingTimestamp > data.timestamp)
      {
        data.sampleRate = sampleRate;
        data.numChannels = numChannels;
        data.samples = audioReadBuffer;
        data.timestamp = recordingTimestamp;
      }
    }
  } // end AudioRecorder::get

  void AudioRecorder::initAudio()
  {
    //clearBuffers(); probably not needed anymore

    pa_sample_spec paSampleSpec;
    paSampleSpec.format   = PA_SAMPLE_S16LE;
    paSampleSpec.rate     = sampleRate;
    paSampleSpec.channels = (uint8_t)numChannels;

    // Create the recording stream
    int error;
    if (!(paSimple = pa_simple_new(NULL, "AudioRecorder", PA_STREAM_RECORD, NULL, "AudioRecorder", &paSampleSpec, NULL, NULL, &error)))
    {
      std::cerr << "[PulseAudio] pa_simple_new() failed: " << pa_strerror(error) << "\n" << std::endl;
      paSimple = NULL;
    }
    else
    {
      std::cout << "[PulseAudio] device opened" << std::endl;
      std::cout << "[PulseAudio] Rate: " << paSampleSpec.rate <<std::endl;
      std::cout << "[PulseAudio] Channels: " << (int) paSampleSpec.channels <<std::endl;
      std::cout << "[PulseAudio] Buffer Size: " << buffer_size <<std::endl;

      initialized = true;
    }
  } //end initAudio

  void AudioRecorder::deinitAudio()
  {
    if (paSimple != NULL)
    {
      initialized = false;
      std::cout << "[PulseAudio] device closed" << std::endl;
      pa_simple_free(paSimple);
      paSimple = NULL;
    }
  } //end deinitAudio

}// end namespace<commit_msg>move variable declaration<commit_after>#include "AudioRecorder.h"

#include <Tools/ThreadUtil.h>
#include "Tools/NaoTime.h"

#include <chrono>
#include <pulse/error.h>

using namespace std;

namespace naoth
{
  AudioRecorder::AudioRecorder()
    :
    audioReadBuffer(BUFFER_SIZE_RX, 0),
    recordingTimestamp(0),
    capture(false),
    running(false),
    initialized(false),
    resetting(false),
    deinitCyclesCounter(0)
  {
    std::cout << "[INFO] AudioRecorder thread started" << std::endl;
    audioRecorderThread = std::thread([this] {this->execute();});
    ThreadUtil::setPriority(audioRecorderThread, ThreadUtil::Priority::lowest);

    //The following parameters are used by bhuman:
    //TODO implement them as controll in AudioData Representation
    /*
    (unsigned)(10) retries,      // Number of tries to open device.
      (unsigned)(500) retryDelay,  //< Delay before a retry to open device.
      (bool)(false) allChannels,   //< Use all 4 channels, instead of only two
      (unsigned)(8000) sampleRate, //< Sample rate to capture. This variable will contain the framerate the driver finally selected.
      (unsigned)(5000) maxFrames,  //< Maximum number of frames read in one cycle.
      (bool)(true) onlySoundInSet, // If true, the module will not provide audio data in game states other than set

    */
  }

  AudioRecorder::~AudioRecorder()
  {
    running = false;

    if(audioRecorderThread.joinable()) {
      audioRecorderThread.join();
    }

    if(initialized) {
      deinitAudio();
    }
  }

  void AudioRecorder::execute()
  {
    running = true;

    // return;
    while(running)
    {
      if(!initialized)
      {
        if(!resetting && capture)
        {
          std::cout << "[AudioRecorder] start recording" << std::endl;
          initAudio();
        }
        else if(resetting)
        {
          usleep(128);
        }
      }
      else
      {
        if(!capture)
        {
          // deinit audio device ~8 seconds after switch off command was set
          // (recording has blocking behaviour 1024 samples equal 128 ms 63*128 equals ~8s
          if(deinitCyclesCounter >= 63)
          {
            std::cout << "stop recording" << std::endl;
            deinitAudio();
            deinitCyclesCounter = 0;
            usleep(128);
            continue;
          }
          deinitCyclesCounter++;
        }
      }

      if(!resetting && initialized)
      {
        //calculate amount of samples needed
        int samplesToRead = SAMPLE_NEW_COUNT * numChannels;
        int bytesToRead = samplesToRead * static_cast<int>(sizeof(short));

        // Record some data
        if (!paSimple || paSimple == NULL)
        {
          std::cerr << "[PulseAudio] pa_simple == NULL" << std::endl;
          running = false;
        }
        //std::cout << "[AudioRecorder] bytesToRead: " << bytesToRead << std::endl;

        int error = 0;
        if (pa_simple_read(paSimple, &audioReadBuffer[0], bytesToRead, &error) < 0)
        {
          std::cerr << "[PulseAudio] pa_simple_read() failed: " << pa_strerror(error) << std::endl;
          running = false;
        } else {
          recordingTimestamp = NaoTime::getNaoTimeInMilliSeconds();
        }
      }
      else
      {
        usleep(128);
        continue;
      }
    } // end while
  } // end execute

  void AudioRecorder::set(const naoth::AudioControl& controlData)
  {
    std::unique_lock<std::mutex> lock(setMutex, std::try_to_lock);
    if ( lock.owns_lock() )
    {
      if(capture != controlData.capture) {
        capture = controlData.capture;
        std::cout << "Capture: " << capture << std::endl;
      }

      if(activeChannels != controlData.activeChannels)
      {
        resetting =  true;
        if(initialized) {
          deinitAudio();
        }

        //clearBuffers(); //TODO are there any buffers to clear?
        activeChannels = controlData.activeChannels;
        numChannels = controlData.numChannels;
        sampleRate = controlData.sampleRate;
        buffer_size = controlData.buffer_size;
        resetting = false;
      }
    }
  }

  void AudioRecorder::get(AudioData& data)
  {
    if (initialized)
    {
      std::unique_lock<std::mutex> lock(getMutex, std::try_to_lock);
      if ( lock.owns_lock() && recordingTimestamp > data.timestamp)
      {
        data.sampleRate = sampleRate;
        data.numChannels = numChannels;
        data.samples = audioReadBuffer;
        data.timestamp = recordingTimestamp;
      }
    }
  } // end AudioRecorder::get

  void AudioRecorder::initAudio()
  {
    //clearBuffers(); probably not needed anymore

    pa_sample_spec paSampleSpec;
    paSampleSpec.format   = PA_SAMPLE_S16LE;
    paSampleSpec.rate     = sampleRate;
    paSampleSpec.channels = (uint8_t)numChannels;

    // Create the recording stream
    int error = 0;
    if (!(paSimple = pa_simple_new(NULL, "AudioRecorder", PA_STREAM_RECORD, NULL, "AudioRecorder", &paSampleSpec, NULL, NULL, &error)))
    {
      std::cerr << "[PulseAudio] pa_simple_new() failed: " << pa_strerror(error) << "\n" << std::endl;
      paSimple = NULL;
    }
    else
    {
      std::cout << "[PulseAudio] device opened" << std::endl;
      std::cout << "[PulseAudio] Rate: " << paSampleSpec.rate <<std::endl;
      std::cout << "[PulseAudio] Channels: " << (int) paSampleSpec.channels <<std::endl;
      std::cout << "[PulseAudio] Buffer Size: " << buffer_size <<std::endl;

      initialized = true;
    }
  } //end initAudio

  void AudioRecorder::deinitAudio()
  {
    if (paSimple != NULL)
    {
      initialized = false;
      std::cout << "[PulseAudio] device closed" << std::endl;
      pa_simple_free(paSimple);
      paSimple = NULL;
    }
  } //end deinitAudio

}// end namespace<|endoftext|>


<commit_before>/* e-agent that moves along road segments and randomly turns at intersections.
*/

#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <string>
#include <cmath>
#include <cassert>
#include <unistd.h>

#include "roadnet.hpp"

#include "ros/ros.h"
#include "tf/tf.h"
#include "nav_msgs/Odometry.h"
#include "gazebo_msgs/ModelStates.h"

#include "geometry_msgs/Twist.h"
#include "sensor_msgs/LaserScan.h"

using namespace dubins_traffic;

const double min_dist = 0.5;
bool safe_to_move = true;

void laser_cb( const sensor_msgs::LaserScan &scan )
{
    for (int i = 0; i < scan.ranges.size(); i++) {
        if (scan.ranges[i] < min_dist) {
            safe_to_move = false;
            return;
        }
    }
    safe_to_move = true;
}

class ModelStatesWatcher {
public:

    ModelStatesWatcher( ros::NodeHandle &nh, std::string topic_name = "/gazebo/model_states" );

    // Callback function for messages from the "/gazebo/model_states" topic
    void ms_cb( const gazebo_msgs::ModelStates &ms );

    /* Get current pose estimate
     *
     * If an estimate is available, return true and place the estimate in the
     * given array. Otherwise, return false and do nothing to the array.
     */
    bool get_pose_estimate( double *x );

    bool is_near_ego_vehicle() const
        { return near_ego_vehicle; }

private:
    double last_mspose[3];
    bool valid_mspose;
    std::string model_name;
    ros::Subscriber mssub;
    bool near_ego_vehicle;
};

ModelStatesWatcher::ModelStatesWatcher( ros::NodeHandle &nh, std::string topic_name )
    : valid_mspose(false), model_name(nh.getNamespace()), near_ego_vehicle(true),
      mssub(nh.subscribe( topic_name, 1, &ModelStatesWatcher::ms_cb, this ))
{
    while (model_name[0] == '/')
        model_name = std::string(model_name.c_str()+1);
}

void ModelStatesWatcher::ms_cb( const gazebo_msgs::ModelStates &ms )
{
    int this_model_idx = -1;
    int ego_model_idx = -1;
    for (int idx = 0; idx < ms.name.size(); idx++) {
        if (ms.name[idx] == model_name) {
            this_model_idx = idx;
            continue;
        }
        if (ms.name[idx] == "ego") {
            ego_model_idx = idx;
            continue;
        }
    }
    if (this_model_idx < 0)
        return;

    if (ego_model_idx >= 0
        && std::sqrt( (ms.pose[this_model_idx].position.x - ms.pose[ego_model_idx].position.x)*(ms.pose[this_model_idx].position.x - ms.pose[ego_model_idx].position.x)
                      + (ms.pose[this_model_idx].position.y - ms.pose[ego_model_idx].position.y)*(ms.pose[this_model_idx].position.y - ms.pose[ego_model_idx].position.y) ) > 1.0) {

        near_ego_vehicle = false;

    } else {

        near_ego_vehicle = true;  // Be cautious

    }

    valid_mspose = false;
    last_mspose[0] = ms.pose[this_model_idx].position.x;
    last_mspose[1] = ms.pose[this_model_idx].position.y;
    last_mspose[2] = tf::getYaw( ms.pose[this_model_idx].orientation );
    valid_mspose = true;
}

bool ModelStatesWatcher::get_pose_estimate( double *x )
{
    if (valid_mspose) {
        for (int i = 0; i < 3; i++)
            x[i] = last_mspose[i];
        return true;
    } else {
        return false;
    }
}

class OdomWatcher {
public:

    OdomWatcher( ros::NodeHandle &nh, std::string topic_name = "odom" );

    // Callback function for messages from the "odom" topic
    void odom_cb( const nav_msgs::Odometry &od );

    /* Get current pose estimate
     *
     * If an estimate is available, return true and place the estimate in the
     * given array. Otherwise, return false and do nothing to the array.
     */
    bool get_pose_estimate( double *x );

private:
    double last_opose[3];
    bool valid_opose;
    ros::Subscriber odomsub;
};

OdomWatcher::OdomWatcher( ros::NodeHandle &nh, std::string topic_name )
    : valid_opose(false),
      odomsub(nh.subscribe( topic_name, 1, &OdomWatcher::odom_cb, this ))
{ }

void OdomWatcher::odom_cb( const nav_msgs::Odometry &od )
{
    valid_opose = false;
    last_opose[0] = od.pose.pose.position.x;
    last_opose[1] = od.pose.pose.position.y;
    last_opose[2] = tf::getYaw( od.pose.pose.orientation );
    valid_opose = true;
}

bool OdomWatcher::get_pose_estimate( double *x )
{
    if (valid_opose) {
        for (int i = 0; i < 3; i++)
            x[i] = last_opose[i];
    }
    return valid_opose;
}

int main( int argc, char **argv )
{
    std::srand( getpid() );

    if (argc <= 1) {
        std::cerr << "Usage: " << argv[0] << " FILE" << std::endl;
        return 1;
    }

    std::ifstream infile( argv[1] );
    if (!infile.is_open()) {
        std::cerr << "Failed to open " << argv[1] << std::endl;
        return 1;
    }
    RoadNetwork rd( infile );
    assert( rd.number_of_segments() > 0 );

    std::pair<size_t, bool> current_segment_idx( std::rand() % rd.number_of_segments(), true );
    Eigen::Vector4d road_segment = rd.mapped_segment( current_segment_idx.first, current_segment_idx.second ? -1 : 1 );
    std::vector<Eigen::Vector2d> waypoints = { Eigen::Vector2d( road_segment(0), road_segment(1) ),
                                               Eigen::Vector2d( road_segment(2), road_segment(3) ) };
/* Pre-generated list of waypoints. This routine will be provided later as an alternative mode.
    std::vector< std::pair<size_t, bool> > visited_indices = {std::pair<size_t, bool>( 0, true )};
    Eigen::Vector4d road_segment = rd.mapped_segment( visited_indices.back().first );

    std::vector<Eigen::Vector2d> waypoints = { Eigen::Vector2d( road_segment(0), road_segment(1) ),
                                               Eigen::Vector2d( road_segment(2), road_segment(3) ) };

    while (true) {
        std::vector<size_t> end_indices;
        if (visited_indices.back().second) {  // Direction on previous segment?
            end_indices = rd.segments_at_end( visited_indices.back().first );
        } else {
            end_indices = rd.segments_at_start( visited_indices.back().first );
        }
        if (end_indices.size() == 0)  // Dead-end
            break;
        std::vector<size_t>::iterator end_it;
        for (end_it = end_indices.begin(); end_it != end_indices.end(); end_it++) {
            std::vector< std::pair<size_t, bool> >::iterator visited_it;
            for (visited_it = visited_indices.begin();
                 visited_it != visited_indices.end(); visited_it++) {
                if ((*visited_it).first == *end_it)
                    break;
            }
            if (visited_it == visited_indices.end())
                break;
        }
        if (end_it != end_indices.end()) {
            Eigen::Vector4d this_segment = rd.mapped_segment( *end_it );
            if ((this_segment.segment<2>(0) - waypoints.back()).norm() < 1e-6) {
                waypoints.push_back( this_segment.segment<2>(2) );
                visited_indices.push_back( std::pair<size_t, bool>( *end_it, true ) );
            } else {
                assert( (this_segment.segment<2>(2) - waypoints.back()).norm() < 1e-6 );
                waypoints.push_back( this_segment.segment<2>(0) );
                visited_indices.push_back( std::pair<size_t, bool>( *end_it, false ) );
            }
        } else {
            break;
        }
    }
*/

    // Configure turning rate and other motion parameters here
    double turning_rate = 0.9;  // rad/s
    double forward_speed = 0.5;  // m/s

    // Thresholds for switching among modes of motion
    double min_angle_err = 0.07;  // Minimum relative angle to drive forward toward waypoint
    double min_reach_err = 0.075;  // Distance from waypoint before it is declared as "reached"

    safe_to_move = true;
    ros::init( argc, argv, "Oscar", ros::init_options::AnonymousName );
    ros::NodeHandle nh;

    ros::Publisher action = nh.advertise<geometry_msgs::Twist>( "cmd_vel", 1 );
    ros::Subscriber lmssub = nh.subscribe( "scan", 10, &laser_cb );

    ModelStatesWatcher pose_watcher( nh );

    int current_index = 0;  // Visit waypoints in order
    double current_pose[3];
    double angle_diff;

    ros::Rate rate( 30. );

    while (ros::ok()) {

        geometry_msgs::Twist mot;

        if (safe_to_move && pose_watcher.get_pose_estimate( current_pose )) {

            angle_diff = atan2( waypoints[current_index](1) - current_pose[1],
                                waypoints[current_index](0) - current_pose[0] ) - current_pose[2];
            while (angle_diff >= M_PI)
                angle_diff -= 2*M_PI;
            while (angle_diff < -M_PI)
                angle_diff += 2*M_PI;

            if (sqrt( (waypoints[current_index](0) - current_pose[0])*(waypoints[current_index](0) - current_pose[0])
                      + (waypoints[current_index](1) - current_pose[1])*(waypoints[current_index](1) - current_pose[1]) ) < min_reach_err) {
                std::cout << "Reached waypoint " << waypoints[current_index].transpose() << std::endl;
                // current_index = (current_index+1) % waypoints.size();
                if (current_index < 1) {
                    current_index++;
                } else {
                    std::vector<size_t> end_indices;
                    if (current_segment_idx.second) {  // Direction on previous segment?
                        end_indices = rd.segments_at_end( current_segment_idx.first );
                    } else {
                        end_indices = rd.segments_at_start( current_segment_idx.first );
                    }
                    if (end_indices.size() == 0) { // Dead-end
                        Eigen::Vector2d tmp = waypoints[0];
                        waypoints[0] = waypoints[current_index];
                        waypoints[current_index] = tmp;
                        current_segment_idx.second = current_segment_idx.second ? false : true;
                    } else {

                        Eigen::Vector4d this_segment = rd.mapped_segment( current_segment_idx.first );
                        waypoints[current_index] = this_segment.segment<2>( current_segment_idx.second ? 2 : 0 );
                        current_segment_idx.first = end_indices[std::rand() % end_indices.size()];
                        this_segment = rd.mapped_segment( current_segment_idx.first );
                        if ((this_segment.segment<2>(0) - waypoints[current_index]).norm() < 1e-6) {
                            current_segment_idx.second = true;
                        } else {
                            assert( (this_segment.segment<2>(2) - waypoints[current_index]).norm() < 1e-6 );
                            current_segment_idx.second = false;
                        }
                        this_segment = rd.mapped_segment( current_segment_idx.first, current_segment_idx.second ? -1 : 1 );
                        waypoints[current_index] = this_segment.segment<2>( current_segment_idx.second ? 2 : 0 );

                    }
                }
            } else if (fabs( angle_diff ) > min_angle_err) {

                if (angle_diff > 0) {
                    mot.angular.z = turning_rate;
                } else {
                    mot.angular.z = -turning_rate;
                }

            } else {
                mot.linear.x = forward_speed;
            }

        }

        if (pose_watcher.is_near_ego_vehicle())
            mot.linear.x = 0.0;

        action.publish( mot );
        ros::spinOnce();
        rate.sleep();
    }

    return 0;
}
<commit_msg>Use std namespace for sqrt() of cmath<commit_after>/* e-agent that moves along road segments and randomly turns at intersections.
*/

#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <string>
#include <cmath>
#include <cassert>
#include <unistd.h>

#include "roadnet.hpp"

#include "ros/ros.h"
#include "tf/tf.h"
#include "nav_msgs/Odometry.h"
#include "gazebo_msgs/ModelStates.h"

#include "geometry_msgs/Twist.h"
#include "sensor_msgs/LaserScan.h"

using namespace dubins_traffic;

const double min_dist = 0.5;
bool safe_to_move = true;

void laser_cb( const sensor_msgs::LaserScan &scan )
{
    for (int i = 0; i < scan.ranges.size(); i++) {
        if (scan.ranges[i] < min_dist) {
            safe_to_move = false;
            return;
        }
    }
    safe_to_move = true;
}

class ModelStatesWatcher {
public:

    ModelStatesWatcher( ros::NodeHandle &nh, std::string topic_name = "/gazebo/model_states" );

    // Callback function for messages from the "/gazebo/model_states" topic
    void ms_cb( const gazebo_msgs::ModelStates &ms );

    /* Get current pose estimate
     *
     * If an estimate is available, return true and place the estimate in the
     * given array. Otherwise, return false and do nothing to the array.
     */
    bool get_pose_estimate( double *x );

    bool is_near_ego_vehicle() const
        { return near_ego_vehicle; }

private:
    double last_mspose[3];
    bool valid_mspose;
    std::string model_name;
    ros::Subscriber mssub;
    bool near_ego_vehicle;
};

ModelStatesWatcher::ModelStatesWatcher( ros::NodeHandle &nh, std::string topic_name )
    : valid_mspose(false), model_name(nh.getNamespace()), near_ego_vehicle(true),
      mssub(nh.subscribe( topic_name, 1, &ModelStatesWatcher::ms_cb, this ))
{
    while (model_name[0] == '/')
        model_name = std::string(model_name.c_str()+1);
}

void ModelStatesWatcher::ms_cb( const gazebo_msgs::ModelStates &ms )
{
    int this_model_idx = -1;
    int ego_model_idx = -1;
    for (int idx = 0; idx < ms.name.size(); idx++) {
        if (ms.name[idx] == model_name) {
            this_model_idx = idx;
            continue;
        }
        if (ms.name[idx] == "ego") {
            ego_model_idx = idx;
            continue;
        }
    }
    if (this_model_idx < 0)
        return;

    if (ego_model_idx >= 0
        && std::sqrt( (ms.pose[this_model_idx].position.x - ms.pose[ego_model_idx].position.x)*(ms.pose[this_model_idx].position.x - ms.pose[ego_model_idx].position.x)
                      + (ms.pose[this_model_idx].position.y - ms.pose[ego_model_idx].position.y)*(ms.pose[this_model_idx].position.y - ms.pose[ego_model_idx].position.y) ) > 1.0) {

        near_ego_vehicle = false;

    } else {

        near_ego_vehicle = true;  // Be cautious

    }

    valid_mspose = false;
    last_mspose[0] = ms.pose[this_model_idx].position.x;
    last_mspose[1] = ms.pose[this_model_idx].position.y;
    last_mspose[2] = tf::getYaw( ms.pose[this_model_idx].orientation );
    valid_mspose = true;
}

bool ModelStatesWatcher::get_pose_estimate( double *x )
{
    if (valid_mspose) {
        for (int i = 0; i < 3; i++)
            x[i] = last_mspose[i];
        return true;
    } else {
        return false;
    }
}

class OdomWatcher {
public:

    OdomWatcher( ros::NodeHandle &nh, std::string topic_name = "odom" );

    // Callback function for messages from the "odom" topic
    void odom_cb( const nav_msgs::Odometry &od );

    /* Get current pose estimate
     *
     * If an estimate is available, return true and place the estimate in the
     * given array. Otherwise, return false and do nothing to the array.
     */
    bool get_pose_estimate( double *x );

private:
    double last_opose[3];
    bool valid_opose;
    ros::Subscriber odomsub;
};

OdomWatcher::OdomWatcher( ros::NodeHandle &nh, std::string topic_name )
    : valid_opose(false),
      odomsub(nh.subscribe( topic_name, 1, &OdomWatcher::odom_cb, this ))
{ }

void OdomWatcher::odom_cb( const nav_msgs::Odometry &od )
{
    valid_opose = false;
    last_opose[0] = od.pose.pose.position.x;
    last_opose[1] = od.pose.pose.position.y;
    last_opose[2] = tf::getYaw( od.pose.pose.orientation );
    valid_opose = true;
}

bool OdomWatcher::get_pose_estimate( double *x )
{
    if (valid_opose) {
        for (int i = 0; i < 3; i++)
            x[i] = last_opose[i];
    }
    return valid_opose;
}

int main( int argc, char **argv )
{
    std::srand( getpid() );

    if (argc <= 1) {
        std::cerr << "Usage: " << argv[0] << " FILE" << std::endl;
        return 1;
    }

    std::ifstream infile( argv[1] );
    if (!infile.is_open()) {
        std::cerr << "Failed to open " << argv[1] << std::endl;
        return 1;
    }
    RoadNetwork rd( infile );
    assert( rd.number_of_segments() > 0 );

    std::pair<size_t, bool> current_segment_idx( std::rand() % rd.number_of_segments(), true );
    Eigen::Vector4d road_segment = rd.mapped_segment( current_segment_idx.first, current_segment_idx.second ? -1 : 1 );
    std::vector<Eigen::Vector2d> waypoints = { Eigen::Vector2d( road_segment(0), road_segment(1) ),
                                               Eigen::Vector2d( road_segment(2), road_segment(3) ) };
/* Pre-generated list of waypoints. This routine will be provided later as an alternative mode.
    std::vector< std::pair<size_t, bool> > visited_indices = {std::pair<size_t, bool>( 0, true )};
    Eigen::Vector4d road_segment = rd.mapped_segment( visited_indices.back().first );

    std::vector<Eigen::Vector2d> waypoints = { Eigen::Vector2d( road_segment(0), road_segment(1) ),
                                               Eigen::Vector2d( road_segment(2), road_segment(3) ) };

    while (true) {
        std::vector<size_t> end_indices;
        if (visited_indices.back().second) {  // Direction on previous segment?
            end_indices = rd.segments_at_end( visited_indices.back().first );
        } else {
            end_indices = rd.segments_at_start( visited_indices.back().first );
        }
        if (end_indices.size() == 0)  // Dead-end
            break;
        std::vector<size_t>::iterator end_it;
        for (end_it = end_indices.begin(); end_it != end_indices.end(); end_it++) {
            std::vector< std::pair<size_t, bool> >::iterator visited_it;
            for (visited_it = visited_indices.begin();
                 visited_it != visited_indices.end(); visited_it++) {
                if ((*visited_it).first == *end_it)
                    break;
            }
            if (visited_it == visited_indices.end())
                break;
        }
        if (end_it != end_indices.end()) {
            Eigen::Vector4d this_segment = rd.mapped_segment( *end_it );
            if ((this_segment.segment<2>(0) - waypoints.back()).norm() < 1e-6) {
                waypoints.push_back( this_segment.segment<2>(2) );
                visited_indices.push_back( std::pair<size_t, bool>( *end_it, true ) );
            } else {
                assert( (this_segment.segment<2>(2) - waypoints.back()).norm() < 1e-6 );
                waypoints.push_back( this_segment.segment<2>(0) );
                visited_indices.push_back( std::pair<size_t, bool>( *end_it, false ) );
            }
        } else {
            break;
        }
    }
*/

    // Configure turning rate and other motion parameters here
    double turning_rate = 0.9;  // rad/s
    double forward_speed = 0.5;  // m/s

    // Thresholds for switching among modes of motion
    double min_angle_err = 0.07;  // Minimum relative angle to drive forward toward waypoint
    double min_reach_err = 0.075;  // Distance from waypoint before it is declared as "reached"

    safe_to_move = true;
    ros::init( argc, argv, "Oscar", ros::init_options::AnonymousName );
    ros::NodeHandle nh;

    ros::Publisher action = nh.advertise<geometry_msgs::Twist>( "cmd_vel", 1 );
    ros::Subscriber lmssub = nh.subscribe( "scan", 10, &laser_cb );

    ModelStatesWatcher pose_watcher( nh );

    int current_index = 0;  // Visit waypoints in order
    double current_pose[3];
    double angle_diff;

    ros::Rate rate( 30. );

    while (ros::ok()) {

        geometry_msgs::Twist mot;

        if (safe_to_move && pose_watcher.get_pose_estimate( current_pose )) {

            angle_diff = atan2( waypoints[current_index](1) - current_pose[1],
                                waypoints[current_index](0) - current_pose[0] ) - current_pose[2];
            while (angle_diff >= M_PI)
                angle_diff -= 2*M_PI;
            while (angle_diff < -M_PI)
                angle_diff += 2*M_PI;

            if (std::sqrt( (waypoints[current_index](0) - current_pose[0])*(waypoints[current_index](0) - current_pose[0])
                           + (waypoints[current_index](1) - current_pose[1])*(waypoints[current_index](1) - current_pose[1]) ) < min_reach_err) {
                std::cout << "Reached waypoint " << waypoints[current_index].transpose() << std::endl;
                // current_index = (current_index+1) % waypoints.size();
                if (current_index < 1) {
                    current_index++;
                } else {
                    std::vector<size_t> end_indices;
                    if (current_segment_idx.second) {  // Direction on previous segment?
                        end_indices = rd.segments_at_end( current_segment_idx.first );
                    } else {
                        end_indices = rd.segments_at_start( current_segment_idx.first );
                    }
                    if (end_indices.size() == 0) { // Dead-end
                        Eigen::Vector2d tmp = waypoints[0];
                        waypoints[0] = waypoints[current_index];
                        waypoints[current_index] = tmp;
                        current_segment_idx.second = current_segment_idx.second ? false : true;
                    } else {

                        Eigen::Vector4d this_segment = rd.mapped_segment( current_segment_idx.first );
                        waypoints[current_index] = this_segment.segment<2>( current_segment_idx.second ? 2 : 0 );
                        current_segment_idx.first = end_indices[std::rand() % end_indices.size()];
                        this_segment = rd.mapped_segment( current_segment_idx.first );
                        if ((this_segment.segment<2>(0) - waypoints[current_index]).norm() < 1e-6) {
                            current_segment_idx.second = true;
                        } else {
                            assert( (this_segment.segment<2>(2) - waypoints[current_index]).norm() < 1e-6 );
                            current_segment_idx.second = false;
                        }
                        this_segment = rd.mapped_segment( current_segment_idx.first, current_segment_idx.second ? -1 : 1 );
                        waypoints[current_index] = this_segment.segment<2>( current_segment_idx.second ? 2 : 0 );

                    }
                }
            } else if (fabs( angle_diff ) > min_angle_err) {

                if (angle_diff > 0) {
                    mot.angular.z = turning_rate;
                } else {
                    mot.angular.z = -turning_rate;
                }

            } else {
                mot.linear.x = forward_speed;
            }

        }

        if (pose_watcher.is_near_ego_vehicle())
            mot.linear.x = 0.0;

        action.publish( mot );
        ros::spinOnce();
        rate.sleep();
    }

    return 0;
}
<|endoftext|>


<commit_before>
#pragma once

#include <tuple>
#include <utility>

#include "quantities/named_quantities.hpp"

namespace principia {
namespace numerics {
namespace internal_polynomial {

using quantities::Derivative;

// TODO(phl): We would like to define NthDerivative in named_quantities.hpp
// thus:
//
//   template<typename Value, typename Argument, int order>
//   using NthDerivative = typename std::conditional_t<
//       order == 0,
//       Value,
//       Quotient<Difference<Value>,
//                Exponentiation<Difference<Argument>, order>>>;
//
//   template<typename Value, typename Argument>
//   using Derivative = NthDerivative<Value, Argument, 1>;
//
// Unfortunately VS2015 is buggy and this interacts poorly with the
// std::integer_sequence below (we get the wrong types).  Revisit once MSFT has
// fixed their bugs.

template<typename Value, typename Argument, int order>
struct NthDerivativeGenerator {
  using Type = Derivative<
      typename NthDerivativeGenerator<Value, Argument, order - 1>::Type,
      Argument>;
};
template<typename Value, typename Argument>
struct NthDerivativeGenerator<Value, Argument, 0> {
  using Type = Value;
};

template<typename Value, typename Argument, int order>
using NthDerivative =
    typename NthDerivativeGenerator<Value, Argument, order>::Type;

template<typename Value, typename Argument, typename>
struct NthDerivativesGenerator;
template<typename Value, typename Argument, int... orders>
struct NthDerivativesGenerator<Value,
                               Argument,
                               std::integer_sequence<int, orders...>> {
  using Type = std::tuple<NthDerivative<Value, Argument, orders>...>;
};

template<typename Value, typename Argument, typename Sequence>
using NthDerivatives =
    typename NthDerivativesGenerator<Value, Argument, Sequence>::Type;

// |Value| must belong to an affine space.  |Argument| must belong to a vector
// space.
template<typename Value, typename Argument>
class Polynomial {
 public:
  virtual Value Evaluate(Argument const& argument) const = 0;
  virtual Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const = 0;

 protected:
  virtual ~Polynomial() = default;
};

template<typename Value, typename Argument, int degree,
         template<typename, typename, int> class Evaluator>
class PolynomialInMonomialBasis : public Polynomial<Value, Argument> {
 public:
  // Equivalent to:
  //   std::tuple<Value,
  //              Derivative<Value, Argument>,
  //              Derivative<Derivative<Value, Argument>>...>
  using Coefficients =
      NthDerivatives<Value,
                     Argument,
                     std::make_integer_sequence<int, degree + 1>>;

  explicit PolynomialInMonomialBasis(Coefficients const& coefficients);

  Value Evaluate(Argument const& argument) const override;
  Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const override;

 private:
  Coefficients coefficients_;
};

}  // namespace internal_polynomial

using internal_polynomial::NthDerivative;
using internal_polynomial::Polynomial;
using internal_polynomial::PolynomialInMonomialBasis;

}  // namespace numerics
}  // namespace principia

#include "numerics/polynomial_body.hpp"
<commit_msg>Top-level inlining.<commit_after>
#pragma once

#include <tuple>
#include <utility>

#include "quantities/named_quantities.hpp"

namespace principia {
namespace numerics {
namespace internal_polynomial {

using quantities::Derivative;

// TODO(phl): We would like to define NthDerivative in named_quantities.hpp
// thus:
//
//   template<typename Value, typename Argument, int order>
//   using NthDerivative = typename std::conditional_t<
//       order == 0,
//       Value,
//       Quotient<Difference<Value>,
//                Exponentiation<Difference<Argument>, order>>>;
//
//   template<typename Value, typename Argument>
//   using Derivative = NthDerivative<Value, Argument, 1>;
//
// Unfortunately VS2015 is buggy and this interacts poorly with the
// std::integer_sequence below (we get the wrong types).  Revisit once MSFT has
// fixed their bugs.

template<typename Value, typename Argument, int order>
struct NthDerivativeGenerator {
  using Type = Derivative<
      typename NthDerivativeGenerator<Value, Argument, order - 1>::Type,
      Argument>;
};
template<typename Value, typename Argument>
struct NthDerivativeGenerator<Value, Argument, 0> {
  using Type = Value;
};

template<typename Value, typename Argument, int order>
using NthDerivative =
    typename NthDerivativeGenerator<Value, Argument, order>::Type;

template<typename Value, typename Argument, typename>
struct NthDerivativesGenerator;
template<typename Value, typename Argument, int... orders>
struct NthDerivativesGenerator<Value,
                               Argument,
                               std::integer_sequence<int, orders...>> {
  using Type = std::tuple<NthDerivative<Value, Argument, orders>...>;
};

template<typename Value, typename Argument, typename Sequence>
using NthDerivatives =
    typename NthDerivativesGenerator<Value, Argument, Sequence>::Type;

// |Value| must belong to an affine space.  |Argument| must belong to a vector
// space.
template<typename Value, typename Argument>
class Polynomial {
 public:
  virtual Value Evaluate(Argument const& argument) const = 0;
  virtual Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const = 0;

 protected:
  virtual ~Polynomial() = default;
};

template<typename Value, typename Argument, int degree,
         template<typename, typename, int> class Evaluator>
class PolynomialInMonomialBasis : public Polynomial<Value, Argument> {
 public:
  // Equivalent to:
  //   std::tuple<Value,
  //              Derivative<Value, Argument>,
  //              Derivative<Derivative<Value, Argument>>...>
  using Coefficients =
      NthDerivatives<Value,
                     Argument,
                     std::make_integer_sequence<int, degree + 1>>;

  explicit PolynomialInMonomialBasis(Coefficients const& coefficients);

  FORCE_INLINE(inline) Value Evaluate(Argument const& argument) const override;
  FORCE_INLINE(inline) Derivative<Value, Argument> EvaluateDerivative(
      Argument const& argument) const override;

 private:
  Coefficients coefficients_;
};

}  // namespace internal_polynomial

using internal_polynomial::NthDerivative;
using internal_polynomial::Polynomial;
using internal_polynomial::PolynomialInMonomialBasis;

}  // namespace numerics
}  // namespace principia

#include "numerics/polynomial_body.hpp"
<|endoftext|>


<commit_before>// FitsRequestHandler.cc

// This file is part of fits_handler, a data handler for the OPeNDAP data
// server.

// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
//
// This library 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 2.1 of the License, or (at your option) any later version.
//
// This library 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 this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact University Corporation for Atmospheric Research at
// 3080 Center Green Drive, Boulder, CO 80301

// (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
// Please read the full copyright statement in the file COPYRIGHT_UCAR.
//
// Authors:
//      pwest       Patrick West <pwest@ucar.edu>
//      jgarcia     Jose Garcia <jgarcia@ucar.edu>

#include "config.h"

#include <DAS.h>
#include <DDS.h>
#include <DMR.h>
#include <D4BaseTypeFactory.h>
#include <Ancillary.h>
#include <InternalErr.h>
#include <mime_util.h>

#include <BESResponseHandler.h>
#include <BESDapError.h>

#include <BESDapNames.h>
#include <BESResponseNames.h>
#include <BESDASResponse.h>
#include <BESDDSResponse.h>
#include <BESDataDDSResponse.h>
#include <BESDMRResponse.h>

#include <BESVersionInfo.h>
#include <BESConstraintFuncs.h>
#include <BESServiceRegistry.h>
#include <BESUtil.h>

#include <fitsio.h>

#include "FitsRequestHandler.h"
#include "fits_read_attributes.h"
#include "fits_read_descriptors.h"

#define FITS_NAME "fits"

FitsRequestHandler::FitsRequestHandler(const string &name) :
		BESRequestHandler(name)
{
	add_handler(DAS_RESPONSE, FitsRequestHandler::fits_build_das);
	add_handler(DDS_RESPONSE, FitsRequestHandler::fits_build_dds);
	add_handler(DATA_RESPONSE, FitsRequestHandler::fits_build_data);

	add_handler(DMR_RESPONSE, FitsRequestHandler::fits_build_dmr);
	add_handler(DAP4DATA_RESPONSE, FitsRequestHandler::fits_build_dmr);

	add_handler(VERS_RESPONSE, FitsRequestHandler::fits_build_vers);
	add_handler(HELP_RESPONSE, FitsRequestHandler::fits_build_help);
}

FitsRequestHandler::~FitsRequestHandler()
{
}

bool FitsRequestHandler::fits_build_das(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(response);
	if (!bdas) throw BESInternalError("cast error", __FILE__, __LINE__);

	try {
		bdas->set_container(dhi.container->get_symbolic_name());
		DAS *das = bdas->get_das();
		string accessed = dhi.container->access();
		string fits_error;
		if (!fits_handler::fits_read_attributes(*das, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_das(*das, accessed);
		bdas->clear_container();
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		throw BESDapError("Unknown exception caught building FITS das response", true, unknown_error, __FILE__, __LINE__);
	}
	return true;
}

bool FitsRequestHandler::fits_build_dds(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(response);
	if (!bdds) throw BESInternalError("cast error", __FILE__, __LINE__);

	try {
		bdds->set_container(dhi.container->get_symbolic_name());
		DDS *dds = bdds->get_dds();
		string accessed = dhi.container->access();
		string fits_error;

		if (!fits_handler::fits_read_descriptors(*dds, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}

		Ancillary::read_ancillary_dds(*dds, accessed);
		DAS *das = new DAS;
		BESDASResponse bdas(das);
		bdas.set_container(dhi.container->get_symbolic_name());
		if (!fits_handler::fits_read_attributes(*das, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_das(*das, accessed);

		dds->transfer_attributes(das);

		bdds->set_constraint(dhi);

		bdds->clear_container();
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		string err = "Unknown exception caught building FITS dds response";
		throw BESDapError(err, true, unknown_error, __FILE__, __LINE__);
	}

	return true;
}

bool FitsRequestHandler::fits_build_data(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(response);
	if (!bdds) throw BESInternalError("cast error", __FILE__, __LINE__);

	try {
		bdds->set_container(dhi.container->get_symbolic_name());
		DataDDS *dds = bdds->get_dds();
		string accessed = dhi.container->access();
		string fits_error;
		if (!fits_handler::fits_read_descriptors(*dds, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_dds(*dds, accessed);

		DAS *das = new DAS;
		BESDASResponse bdas(das);
		bdas.set_container(dhi.container->get_symbolic_name());
		if (!fits_handler::fits_read_attributes(*das, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_das(*das, accessed);

		dds->transfer_attributes(das);

		bdds->set_constraint(dhi);

		bdds->clear_container();
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		string err = "Unknown exception caught building FITS data response";
		throw BESDapError(err, true, unknown_error, __FILE__, __LINE__);
	}

	return true;
}

/**
 * Build a DMR object. This method builds a DMR by first building a DDS
 * that is loaded with attributes and then using that to make a DMR. This
 * method can be used by both the DAP4 metadata and data responses - because
 * the DMR is the C++ object used for both by libdap.
 *
 * @note The CSV handler has a version of this method that contains some
 * more commentary.
 *
 * @param dhi
 * @return true or throws an exception on error
 */
bool FitsRequestHandler::fits_build_dmr(BESDataHandlerInterface &dhi)
{
	string data_path = dhi.container->access();

	BaseTypeFactory factory;
	DDS dds(&factory, name_path(data_path), "3.2");
	dds.filename(data_path);

	try {
		string fits_error;

		if (!fits_handler::fits_read_descriptors(dds, data_path, fits_error))
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);

		DAS das;
		if (!fits_handler::fits_read_attributes(das, data_path, fits_error))
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		Ancillary::read_ancillary_das(das, data_path);

		dds.transfer_attributes(&das);
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		throw BESDapError("Unknown exception caught building FITS data response", true, unknown_error, __FILE__, __LINE__);
	}

	// Make a DMR using the DDS
	DMR *built_dmr = new DMR(new D4BaseTypeFactory, dds);

	// Extract the DMR Response object - this holds the DMR used by the
	// other parts of the framework.
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDMRResponse &bdmr = dynamic_cast<BESDMRResponse &>(*response);

	// Remove the existing DMR and set the newly made one
	DMR *dmr = bdmr.get_dmr();
	delete dmr->factory();
	delete dmr;
	bdmr.set_dmr(built_dmr);	// BESDMRResponse will delete this object

	bdmr.set_dap4_constraint(dhi);
	bdmr.set_dap4_function(dhi);

	return true;
}

bool FitsRequestHandler::fits_build_vers(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESVersionInfo *info = dynamic_cast<BESVersionInfo *>(response);
	if (!info) throw BESInternalError("cast error", __FILE__, __LINE__);

	info->add_module(PACKAGE_NAME, PACKAGE_VERSION);

	return true;
}

bool FitsRequestHandler::fits_build_help(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESInfo *info = dynamic_cast<BESInfo *>(response);
	if (!info) throw BESInternalError("cast error", __FILE__, __LINE__);

	map<string, string> attrs;
	attrs["name"] = PACKAGE_NAME;
	attrs["version"] = PACKAGE_VERSION;
	list<string> services;
	BESServiceRegistry::TheRegistry()->services_handled(FITS_NAME, services);
	if (services.size() > 0) {
		string handles = BESUtil::implode(services, ',');
		attrs["handles"] = handles;
	}
	info->begin_tag("module", &attrs);
	info->end_tag("module");

	return true;
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance, the name of the request
 * handler, and the names of all registered handler functions
 *
 * @param strm C++ i/o stream to dump the information to
 */
void FitsRequestHandler::dump(ostream &strm) const
{
	strm << BESIndent::LMarg << "FitsRequestHandler::dump - (" << (void *) this << ")" << endl;
	BESIndent::Indent();
	BESRequestHandler::dump(strm);
	BESIndent::UnIndent();
}

<commit_msg>Error message text fixed.<commit_after>// FitsRequestHandler.cc

// This file is part of fits_handler, a data handler for the OPeNDAP data
// server.

// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
//
// This library 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 2.1 of the License, or (at your option) any later version.
//
// This library 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 this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact University Corporation for Atmospheric Research at
// 3080 Center Green Drive, Boulder, CO 80301

// (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
// Please read the full copyright statement in the file COPYRIGHT_UCAR.
//
// Authors:
//      pwest       Patrick West <pwest@ucar.edu>
//      jgarcia     Jose Garcia <jgarcia@ucar.edu>

#include "config.h"

#include <DAS.h>
#include <DDS.h>
#include <DMR.h>
#include <D4BaseTypeFactory.h>
#include <Ancillary.h>
#include <InternalErr.h>
#include <mime_util.h>

#include <BESResponseHandler.h>
#include <BESDapError.h>

#include <BESDapNames.h>
#include <BESResponseNames.h>
#include <BESDASResponse.h>
#include <BESDDSResponse.h>
#include <BESDataDDSResponse.h>
#include <BESDMRResponse.h>

#include <BESVersionInfo.h>
#include <BESConstraintFuncs.h>
#include <BESServiceRegistry.h>
#include <BESUtil.h>

#include <fitsio.h>

#include "FitsRequestHandler.h"
#include "fits_read_attributes.h"
#include "fits_read_descriptors.h"

#define FITS_NAME "fits"

FitsRequestHandler::FitsRequestHandler(const string &name) :
		BESRequestHandler(name)
{
	add_handler(DAS_RESPONSE, FitsRequestHandler::fits_build_das);
	add_handler(DDS_RESPONSE, FitsRequestHandler::fits_build_dds);
	add_handler(DATA_RESPONSE, FitsRequestHandler::fits_build_data);

	add_handler(DMR_RESPONSE, FitsRequestHandler::fits_build_dmr);
	add_handler(DAP4DATA_RESPONSE, FitsRequestHandler::fits_build_dmr);

	add_handler(VERS_RESPONSE, FitsRequestHandler::fits_build_vers);
	add_handler(HELP_RESPONSE, FitsRequestHandler::fits_build_help);
}

FitsRequestHandler::~FitsRequestHandler()
{
}

bool FitsRequestHandler::fits_build_das(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(response);
	if (!bdas) throw BESInternalError("cast error", __FILE__, __LINE__);

	try {
		bdas->set_container(dhi.container->get_symbolic_name());
		DAS *das = bdas->get_das();
		string accessed = dhi.container->access();
		string fits_error;
		if (!fits_handler::fits_read_attributes(*das, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_das(*das, accessed);
		bdas->clear_container();
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		throw BESDapError("Unknown exception caught building FITS das response", true, unknown_error, __FILE__, __LINE__);
	}
	return true;
}

bool FitsRequestHandler::fits_build_dds(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(response);
	if (!bdds) throw BESInternalError("cast error", __FILE__, __LINE__);

	try {
		bdds->set_container(dhi.container->get_symbolic_name());
		DDS *dds = bdds->get_dds();
		string accessed = dhi.container->access();
		string fits_error;

		if (!fits_handler::fits_read_descriptors(*dds, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}

		Ancillary::read_ancillary_dds(*dds, accessed);
		DAS *das = new DAS;
		BESDASResponse bdas(das);
		bdas.set_container(dhi.container->get_symbolic_name());
		if (!fits_handler::fits_read_attributes(*das, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_das(*das, accessed);

		dds->transfer_attributes(das);

		bdds->set_constraint(dhi);

		bdds->clear_container();
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		string err = "Unknown exception caught building FITS dds response";
		throw BESDapError(err, true, unknown_error, __FILE__, __LINE__);
	}

	return true;
}

bool FitsRequestHandler::fits_build_data(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(response);
	if (!bdds) throw BESInternalError("cast error", __FILE__, __LINE__);

	try {
		bdds->set_container(dhi.container->get_symbolic_name());
		DataDDS *dds = bdds->get_dds();
		string accessed = dhi.container->access();
		string fits_error;
		if (!fits_handler::fits_read_descriptors(*dds, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_dds(*dds, accessed);

		DAS *das = new DAS;
		BESDASResponse bdas(das);
		bdas.set_container(dhi.container->get_symbolic_name());
		if (!fits_handler::fits_read_attributes(*das, accessed, fits_error)) {
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		}
		Ancillary::read_ancillary_das(*das, accessed);

		dds->transfer_attributes(das);

		bdds->set_constraint(dhi);

		bdds->clear_container();
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		string err = "Unknown exception caught building FITS data response";
		throw BESDapError(err, true, unknown_error, __FILE__, __LINE__);
	}

	return true;
}

/**
 * Build a DMR object. This method builds a DMR by first building a DDS
 * that is loaded with attributes and then using that to make a DMR. This
 * method can be used by both the DAP4 metadata and data responses - because
 * the DMR is the C++ object used for both by libdap.
 *
 * @note The CSV handler has a version of this method that contains some
 * more commentary.
 *
 * @param dhi
 * @return true or throws an exception on error
 */
bool FitsRequestHandler::fits_build_dmr(BESDataHandlerInterface &dhi)
{
	string data_path = dhi.container->access();

	BaseTypeFactory factory;
	DDS dds(&factory, name_path(data_path), "3.2");
	dds.filename(data_path);

	try {
		string fits_error;

		if (!fits_handler::fits_read_descriptors(dds, data_path, fits_error))
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);

		DAS das;
		if (!fits_handler::fits_read_attributes(das, data_path, fits_error))
			throw BESDapError(fits_error, false, unknown_error, __FILE__, __LINE__);
		Ancillary::read_ancillary_das(das, data_path);

		dds.transfer_attributes(&das);
	}
	catch( InternalErr &e ) {
		throw BESDapError(e.get_error_message(), true, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( Error &e ) {
		throw BESDapError(e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
	}
	catch( ... ) {
		throw BESDapError("Unknown exception caught building FITS DMR response", true, unknown_error, __FILE__, __LINE__);
	}

	// Make a DMR using the DDS
	DMR *built_dmr = new DMR(new D4BaseTypeFactory, dds);

	// Extract the DMR Response object - this holds the DMR used by the
	// other parts of the framework.
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESDMRResponse &bdmr = dynamic_cast<BESDMRResponse &>(*response);

	// Remove the existing DMR and set the newly made one
	DMR *dmr = bdmr.get_dmr();
	delete dmr->factory();
	delete dmr;
	bdmr.set_dmr(built_dmr);	// BESDMRResponse will delete this object

	bdmr.set_dap4_constraint(dhi);
	bdmr.set_dap4_function(dhi);

	return true;
}

bool FitsRequestHandler::fits_build_vers(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESVersionInfo *info = dynamic_cast<BESVersionInfo *>(response);
	if (!info) throw BESInternalError("cast error", __FILE__, __LINE__);

	info->add_module(PACKAGE_NAME, PACKAGE_VERSION);

	return true;
}

bool FitsRequestHandler::fits_build_help(BESDataHandlerInterface &dhi)
{
	BESResponseObject *response = dhi.response_handler->get_response_object();
	BESInfo *info = dynamic_cast<BESInfo *>(response);
	if (!info) throw BESInternalError("cast error", __FILE__, __LINE__);

	map<string, string> attrs;
	attrs["name"] = PACKAGE_NAME;
	attrs["version"] = PACKAGE_VERSION;
	list<string> services;
	BESServiceRegistry::TheRegistry()->services_handled(FITS_NAME, services);
	if (services.size() > 0) {
		string handles = BESUtil::implode(services, ',');
		attrs["handles"] = handles;
	}
	info->begin_tag("module", &attrs);
	info->end_tag("module");

	return true;
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance, the name of the request
 * handler, and the names of all registered handler functions
 *
 * @param strm C++ i/o stream to dump the information to
 */
void FitsRequestHandler::dump(ostream &strm) const
{
	strm << BESIndent::LMarg << "FitsRequestHandler::dump - (" << (void *) this << ")" << endl;
	BESIndent::Indent();
	BESRequestHandler::dump(strm);
	BESIndent::UnIndent();
}

<|endoftext|>


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

/* $Id$ */

//////////////////////////////////////////////////////////////////////////
//  marian.ivanov@cern.ch
//  Utilities for file merging.
//  Additional functionality on top of the standard TFileMerger:
//
//  1. Possibility to Set the reject/accept list.
//     1.a)  Only entries selected in accept list are merged. By default all entries are selected
//           use AddAccept 0 to specify your desired entry
//     1.b)  Entries selected in reject list are not merged. By default the reject list is empty.
//
//  2. syswatch.log is created diring mergin procedure.
//     Memeory consumption - for reading and for merging can be monitored

/*
  Usage:
  // Libraries for all classes to be merged should be loaded before using the class
  gSystem->Load("libANALYSIS");
  gSystem->Load("libANALYSIScalib");
  gSystem->Load("libTPCcalib");
  TH1::AddDirectory(0);

  //Example usage starting from the input data list in text file:
  //
  AliFileMerger merger;
  merger.AddReject("esdFriend");
  merger.IterTXT("calib.list","CalibObjects.root",kFALSE);
  //

*/
//////////////////////////////////////////////////////////////////////////

#include <fstream>
#include "TSystem.h"
#include "TFile.h"
#include "TGrid.h"
#include "TGridResult.h"
#include "TObjString.h"
#include "TObjArray.h"
#include "TMethodCall.h"

#include "AliSysInfo.h"
#include "AliFileMerger.h"

ClassImp(AliFileMerger)

////////////////////////////////////////////////////////////////////////

AliFileMerger::AliFileMerger():
  TNamed(),
  fRejectMask(0),
  fAcceptMask(0)
{
  //
  // Default constructor
  //
}

//______________________________________________________________________

AliFileMerger::AliFileMerger(const char* name):
  TNamed(name,name),
  fRejectMask(0),
  fAcceptMask(0)
{
  //
  //
  //
}

void AliFileMerger::IterAlien(const char* outputDir, const char* outputFileName, const char* pattern){

  //
  // Merge the files coming out of the calibration job
  //

  TObjArray * mergeArray= new TObjArray;

  TString outputFile(outputFileName);
  TString command;
  // looking for files to be merged in the output directory
  command = Form("find %s/ *%s", outputDir, pattern);
  printf("command: %s\n", command.Data());
  TGrid::Connect("alien://");
  TGridResult *res = gGrid->Command(command);
  if (!res) return;
  TIter nextmap(res);
  TMap *map = 0;
  // loop over the results
  while((map=(TMap*)nextmap())) {
    // getting the turl
    TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
    if (!objs || !objs->GetString().Length()) {
      // Nothing found - skip this output
      delete res;
      break;
    }
    printf("looking for file %s\n",(objs->GetString()).Data());
    TFile* currentFile=TFile::Open((objs->GetString()).Data());
    if(!currentFile) continue; // protection
    Merge(currentFile, mergeArray);

    if(currentFile) delete currentFile;
  }
  Bool_t separate = kFALSE;
  if (separate) {
    StoreSeparateResults(mergeArray,outputFileName);
  }
  else {
    StoreResults(mergeArray,outputFileName);
  }
  delete mergeArray;
  delete res;

}

void AliFileMerger::IterTXT( const char * fileList,  const char* outputFileName, Bool_t separate){

  // Merge the files indicated in the list - fileList
  // ASCII file option example:
  // find `pwd`/ | grep AliESDfriends_v1.root > calib.list

  TObjArray * mergeArray= new TObjArray;

  // Open the input stream

  ifstream in;
  in.open(fileList);
  // Read the input list of files
  TString objfile;
  Int_t counter=0;
  while(in.good()) {
    in >> objfile;
    if (!objfile.Contains("root")) continue; // protection
    printf("Open file:Counter\t%d\tMerging file %s\n",counter++,objfile.Data());
    TFile currentFile(objfile.Data());
    Merge(&currentFile, mergeArray);
  }
  if (separate) {
    StoreSeparateResults(mergeArray, outputFileName);
  }
  else {
    StoreResults(mergeArray, outputFileName);
  }

  delete mergeArray;
}

void AliFileMerger::StoreResults(TObjArray * array, const char* outputFileName){
  //
  // Storing the results in one single file
  //
  TFile *f = new TFile(outputFileName,"recreate");
  for (Int_t i=0; i<array->GetEntries(); i++){
    TObject *object0 = array->At(i);
    if (!object0) continue;
    object0->Write();
  }
  f->Close();
  delete f;
}

void AliFileMerger::StoreSeparateResults(TObjArray * array, const char* outputFileName){
  //
  // Store the results in separate files (one per object)
  //
  for (Int_t i=0; i<array->GetEntries(); i++){
    TObject *object0 = array->At(i);
    if (!object0) continue;
    TFile *f = new TFile(Form("%s_%s.root",outputFileName,object0->GetName()),"recreate");
    object0->Write();
    f->Close();
    delete f;
  }
}

void AliFileMerger::Merge(TFile* fileIn, TObjArray * array){
  //
  // Merging procedure
  //
  static Int_t counter=-1;
  counter++;
  TObjArray *carray = new TObjArray;   //array of the objects inside current file
  carray->SetOwner(kTRUE);

  // load all objects to  memory

  TList *farr = fileIn->GetListOfKeys();
  if (!farr) {
    delete carray;
    return;
  }
  for (Int_t ical=0; ical<farr->GetEntries(); ical++){
    if (!farr->At(ical)) continue;
    TString name(farr->At(ical)->GetName());
    if (!IsAccepted(name)) continue;                        // skip not accepted entries
    TObject *obj = fileIn->Get(name.Data());
    if (obj) carray->AddLast(obj);
    AliSysInfo::AddStamp(name.Data(),1,ical,counter);
  }

  if (carray->GetEntries()==0)  {
    delete carray;
    return;
  }
  TMethodCall callEnv;

  for (Int_t i=0; i<carray->GetEntries(); i++){

    TObjArray *templist = new TObjArray(1);
    templist->SetOwner(kFALSE);
    TObject *currentObject = carray->At(i);
    if (!currentObject) {
      delete templist;
      continue;
    }
    printf("%s\n",currentObject->GetName());
    callEnv.InitWithPrototype(currentObject->IsA(), "Merge", "TCollection*");
    if (!callEnv.IsValid()) {
      delete templist;
      continue;
    }
    TString oname=currentObject->GetName();
    TObject *mergedObject = array->FindObject(currentObject->GetName());
    if (!mergedObject) {
      array->AddLast(currentObject);
      carray->RemoveAt(i);
      delete templist;
      continue;
    }
    templist->AddLast(currentObject);
    callEnv.SetParam((Long_t) templist);
    callEnv.Execute(mergedObject);
    AliSysInfo::AddStamp(currentObject->GetName(),2,i,counter);
    delete templist;
  }
  delete carray;
}

Bool_t AliFileMerger::IsAccepted(TString name){
  //
  // Accept/reject logic
  // name - name of the entry
  //
  //  if fAcceptMask specified   - entry has to be in list of selected
  //  if fRejectMask speciefied  - entry with name speciief in the list are rejected
  //
  Bool_t accept=kTRUE;
  if (fAcceptMask){
    //
    accept=kFALSE;
    for (Int_t iaccept=0; iaccept<fAcceptMask->GetEntries(); iaccept++){
      if (name.Contains(fAcceptMask->At(iaccept)->GetName())) accept=kTRUE;   // entry was selected
    }
  }
  if (!accept) return kFALSE;

  if (fRejectMask){
    //
    for (Int_t ireject=0; ireject<fRejectMask->GetEntries(); ireject++){
      if (name.Contains(fRejectMask->At(ireject)->GetName())) accept=kFALSE;   // entry was rejected
    }
  }
  return accept;
}

void AliFileMerger::AddReject(const char *reject){
  //
  // add reject string to the list of entries to be rejected for merging
  //
  if (!fRejectMask) fRejectMask = new TObjArray;
  fRejectMask->AddLast(new TObjString(reject));
}
void AliFileMerger::AddAccept(const char *accept){
  //
  // add reject string to the list of entries to be rejected for merging
  //
  if (!fAcceptMask) fAcceptMask = new TObjArray;
  fAcceptMask->AddLast(new TObjString(accept));

}

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

/* $Id$ */

//////////////////////////////////////////////////////////////////////////
//  marian.ivanov@cern.ch
//  Utilities for file merging.
//  Additional functionality on top of the standard TFileMerger:
//
//  1. Possibility to Set the reject/accept list.
//     1.a)  Only entries selected in accept list are merged. By default all entries are selected
//           use AddAccept 0 to specify your desired entry
//     1.b)  Entries selected in reject list are not merged. By default the reject list is empty.
//
//  2. syswatch.log is created diring mergin procedure.
//     Memeory consumption - for reading and for merging can be monitored

/*
  Usage:
  // Libraries for all classes to be merged should be loaded before using the class
  gSystem->Load("libANALYSIS");
  gSystem->Load("libANALYSIScalib");
  gSystem->Load("libTPCcalib");
  TH1::AddDirectory(0);

  //Example usage starting from the input data list in text file:
  //
  AliFileMerger merger;
  merger.AddReject("esdFriend");
  merger.IterTXT("calib.list","CalibObjects.root",kFALSE);
  //

*/
//////////////////////////////////////////////////////////////////////////

#include <fstream>
#include "TSystem.h"
#include "TFile.h"
#include "TGrid.h"
#include "TGridResult.h"
#include "TObjString.h"
#include "TObjArray.h"
#include "TMethodCall.h"

#include "AliSysInfo.h"
#include "AliFileMerger.h"

ClassImp(AliFileMerger)

////////////////////////////////////////////////////////////////////////

AliFileMerger::AliFileMerger():
  TNamed(),
  fRejectMask(0),
  fAcceptMask(0)
{
  //
  // Default constructor
  //
}

//______________________________________________________________________

AliFileMerger::AliFileMerger(const char* name):
  TNamed(name,name),
  fRejectMask(0),
  fAcceptMask(0)
{
  //
  //
  //
}

void AliFileMerger::IterAlien(const char* outputDir, const char* outputFileName, const char* pattern){

  //
  // Merge the files coming out of the calibration job
  //

  TObjArray * mergeArray= new TObjArray;

  TString outputFile(outputFileName);
  TString command;
  // looking for files to be merged in the output directory
  command = Form("find %s/ *%s", outputDir, pattern);
  printf("command: %s\n", command.Data());
  TGrid::Connect("alien://");
  TGridResult *res = gGrid->Command(command);
  if (!res) return;
  TIter nextmap(res);
  TMap *map = 0;
  // loop over the results
  while((map=(TMap*)nextmap())) {
    // getting the turl
    TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
    if (!objs || !objs->GetString().Length()) {
      // Nothing found - skip this output
      delete res;
      break;
    }
    printf("looking for file %s\n",(objs->GetString()).Data());
    TFile* currentFile=TFile::Open((objs->GetString()).Data());
    if(!currentFile) continue; // protection
    Merge(currentFile, mergeArray);

    if(currentFile) delete currentFile;
  }
  Bool_t separate = kFALSE;
  if (separate) {
    StoreSeparateResults(mergeArray,outputFileName);
  }
  else {
    StoreResults(mergeArray,outputFileName);
  }
  delete mergeArray;
  delete res;

}

void AliFileMerger::IterTXT( const char * fileList,  const char* outputFileName, Bool_t separate){

  // Merge the files indicated in the list - fileList
  // ASCII file option example:
  // find `pwd`/ | grep AliESDfriends_v1.root > calib.list

  TObjArray * mergeArray= new TObjArray;

  // Open the input stream

  ifstream in;
  in.open(fileList);
  // Read the input list of files
  TString objfile;
  Int_t counter=0;
  while(in.good()) {
    in >> objfile;
    if (!objfile.Contains("root")) continue; // protection
    printf("Open file:Counter\t%d\tMerging file %s\n",counter++,objfile.Data());
    TFile currentFile(objfile.Data());
    Merge(&currentFile, mergeArray);
  }
  if (separate) {
    StoreSeparateResults(mergeArray, outputFileName);
  }
  else {
    StoreResults(mergeArray, outputFileName);
  }

  delete mergeArray;
}

void AliFileMerger::StoreResults(TObjArray * array, const char* outputFileName){
  //
  // Storing the results in one single file
  //
  TFile *f = new TFile(outputFileName,"recreate");
  for (Int_t i=0; i<array->GetEntries(); i++){
    TObject *object0 = array->At(i);
    if (!object0) continue;
    object0->Write();
  }
  f->Close();
  delete f;
}

void AliFileMerger::StoreSeparateResults(TObjArray * array, const char* outputFileName){
  //
  // Store the results in separate files (one per object)
  //
  for (Int_t i=0; i<array->GetEntries(); i++){
    TObject *object0 = array->At(i);
    if (!object0) continue;
    TFile *f = new TFile(Form("%s_%s.root",outputFileName,object0->GetName()),"recreate");
    object0->Write();
    f->Close();
    delete f;
  }
}

void AliFileMerger::Merge(TFile* fileIn, TObjArray * array){
  //
  // Merging procedure
  //
  if (!array) return;
  static Int_t counter=-1;
  counter++;
  TObjArray *carray = new TObjArray;   //array of the objects inside current file
  carray->SetOwner(kTRUE);

  // load all objects to  memory

  TList *farr = fileIn->GetListOfKeys();
  if (!farr) {
    delete carray;
    return;
  }
  for (Int_t ical=0; ical<farr->GetEntries(); ical++){
    if (!farr->At(ical)) continue;
    TString name(farr->At(ical)->GetName());
    if (!IsAccepted(name)) continue;                        // skip not accepted entries
    TObject *obj = fileIn->Get(name.Data());
    if (obj) carray->AddLast(obj);
    AliSysInfo::AddStamp(name.Data(),1,ical,counter);
  }

  if (carray->GetEntries()==0)  {
    delete carray;
    return;
  }
  TMethodCall callEnv;
  Int_t entries =carray->GetEntriesFast();
  for (Int_t i=0; i<entries; i++){

    TObjArray *templist = new TObjArray(1);
    templist->SetOwner(kFALSE);
    TObject *currentObject = carray->At(i);
    if (!currentObject) {
      delete templist;
      continue;
    }
    printf("%s\n",currentObject->GetName());
    callEnv.InitWithPrototype(currentObject->IsA(), "Merge", "TCollection*");
    if (!callEnv.IsValid()) {
      delete templist;
      continue;
    }
    TString oname=currentObject->GetName();
    TObject *mergedObject = array->FindObject(currentObject->GetName());
    if (!mergedObject) {
      array->AddLast(currentObject);
      carray->RemoveAt(i);
      delete templist;
      continue;
    }
    templist->AddLast(currentObject);
    callEnv.SetParam((Long_t) templist);
    callEnv.Execute(mergedObject);
    AliSysInfo::AddStamp(currentObject->GetName(),2,i,counter);
    delete templist;
  }
  carray->Delete();
  delete carray;
}

Bool_t AliFileMerger::IsAccepted(TString name){
  //
  // Accept/reject logic
  // name - name of the entry
  //
  //  if fAcceptMask specified   - entry has to be in list of selected
  //  if fRejectMask speciefied  - entry with name speciief in the list are rejected
  //
  Bool_t accept=kTRUE;
  if (fAcceptMask){
    //
    accept=kFALSE;
    for (Int_t iaccept=0; iaccept<fAcceptMask->GetEntries(); iaccept++){
      if (name.Contains(fAcceptMask->At(iaccept)->GetName())) accept=kTRUE;   // entry was selected
    }
  }
  if (!accept) return kFALSE;

  if (fRejectMask){
    //
    for (Int_t ireject=0; ireject<fRejectMask->GetEntries(); ireject++){
      if (name.Contains(fRejectMask->At(ireject)->GetName())) accept=kFALSE;   // entry was rejected
    }
  }
  return accept;
}

void AliFileMerger::AddReject(const char *reject){
  //
  // add reject string to the list of entries to be rejected for merging
  //
  if (!fRejectMask) fRejectMask = new TObjArray;
  fRejectMask->AddLast(new TObjString(reject));
}
void AliFileMerger::AddAccept(const char *accept){
  //
  // add reject string to the list of entries to be rejected for merging
  //
  if (!fAcceptMask) fAcceptMask = new TObjArray;
  fAcceptMask->AddLast(new TObjString(accept));

}

<|endoftext|>