odin-detector/odin-data

View on GitHub
cpp/frameReceiver/src/FrameDecoder.cpp

Summary

Maintainability
Test Coverage
/*
 * FrameDecoder.cpp - abstract base class for frameReceiver decoder plugins
 *
 *  Created on: Nov 6, 2017
 *      Author: Tim Nicholls, STFC Application Engineering Group
 */

#include "FrameDecoder.h"
#include "FrameReceiverDefaults.h"

using namespace FrameReceiver;

//! Constructor for the FrameDecoder class.
//!
//! This method initialises the base class of each frame decoder, storing default values
//! for base configuration parameters and variables.
//!
FrameDecoder::FrameDecoder() :
     logger_(Logger::getLogger("FR.FrameDecoder")),
     enable_packet_logging_(FrameReceiver::Defaults::default_enable_packet_logging),
     frame_timeout_ms_(FrameReceiver::Defaults::default_frame_timeout_ms),
     frames_timedout_(0),
     frames_dropped_(0)
{
};

//! This overload is scheduled for deletion; logger is unused.
void FrameDecoder::init(LoggerPtr& logger, OdinData::IpcMessage& config_msg)
{
    init(config_msg);
}

//! Initialise the FrameDecoder class
//!
//! This method initialises the base FrameDecoder class, extracting and storing the appropriate
//! parameters from the configuration message.
//!
//! \param[in] config_msg - IpcMessage containing decoder configuration parameters
//!
void FrameDecoder::init(OdinData::IpcMessage& config_msg)
{
   enable_packet_logging_ = config_msg.get_param<bool>(
       CONFIG_DECODER_ENABLE_PACKET_LOGGING, enable_packet_logging_);
   frame_timeout_ms_ = config_msg.get_param<unsigned int>(
       CONFIG_DECODER_FRAME_TIMEOUT_MS, frame_timeout_ms_);

   // Retrieve the packet logger instance
   packet_logger_ = Logger::getLogger("FR.PacketLogger");
}

//
//! Handle a configuration request from the controlling application.
//!
//! This method handles a configuration request from the controlling application, populating
//! the parameter block of the reply message with decoder parameters using the specified
//! parameter prefix. This method should be overridden by derived decoder classes and then called
//! by the overridden method to populate base class parameters.
//!
//! \param[in] param_prefix - parameter prefix to use on all parameter names
//! \param[in,out] config_reply - reply IpcMessage to populate with parameters
//!
void FrameDecoder::request_configuration(const std::string param_prefix,
    OdinData::IpcMessage& config_reply)
{
    config_reply.set_param(param_prefix + CONFIG_DECODER_ENABLE_PACKET_LOGGING, enable_packet_logging_);
    config_reply.set_param(param_prefix + CONFIG_DECODER_FRAME_TIMEOUT_MS, frame_timeout_ms_);
}

//! Register a buffer manager with the decoder.
//!
//! This method registers a SharedBufferManager instance with the decoder, to be used when
//! receiving, decoding and storing incoming data.
//!
//! \param[in] buffer_manager - pointer to a SharedBufferManager instance
//!
void FrameDecoder::register_buffer_manager(OdinData::SharedBufferManagerPtr buffer_manager)
{
    buffer_manager_ = buffer_manager;
}

//! Register a frame ready callback with the decoder.
//!
//! This method is used to register a frame ready callback function with the decoder, which is
//! called when the decoder determines that a frame is ready to be released to the downstream
//! processing application.
//!
//! \param[in] callback - callback function with the appropriate signature
//!
void FrameDecoder::register_frame_ready_callback(FrameReadyCallback callback)
  {
      ready_callback_ = callback;
  }

//! Push an buffer onto the empty buffer queue.
//!
//! This method is used to add an empty buffer to the tail of the internal empty buffer
//! queue for subsequent use receiving frame data
//!
//! \param[in] buffer_id - SharedBufferManager buffer ID
//!
void FrameDecoder::push_empty_buffer(int buffer_id)
{
    empty_buffer_queue_.push(buffer_id);
}

//! Get the number of empty buffers queued.
//!
//! This method returns the number of buffers currently queued by the decoder in the empty
//! buffer queue
//!
//! \return number of empty buffers queued
//!
const size_t FrameDecoder::get_num_empty_buffers(void) const
{
    return empty_buffer_queue_.size();
}

//! Get the number of mapped buffers currently held.
//!
//! This method returns the number of buffers currently mapped to incoming frames by the
//! decoder, i.e. frames which are being filled but are not yet ready for processing.
//!
//! \return - number of buffers currently mapped for incoming frames
//!
const size_t FrameDecoder::get_num_mapped_buffers(void) const
{
    return frame_buffer_map_.size();
}

//! Get the current frame timeout value.
//!
//! This method returns the frame timeout in milliseconds currently configured in the decoder.
//!
//! \return - current frame timeout in milliseconds
//!
const unsigned int FrameDecoder::get_frame_timeout_ms(void) const
{
    return frame_timeout_ms_;
}

//! Get the number of frames timed out in the decoder
//!
//! This method returns the number of frames that have timed out during reception
//! by the frame decoder. This is typically determined by specialised decoders subclassed
//! from this class.
//!
//! \return - number of frames timed out
//!
const unsigned int FrameDecoder::get_num_frames_timedout(void) const
{
    return frames_timedout_;
}

//! Get the number of frames dropped in the decoder
//!
//! This method returns the number of frames that have been dropped by the frame decoder.
//! This is typically determined by specialised decoders subclassed from this class.
//!
//! \return - number of frames dropped
//!
const unsigned int FrameDecoder::get_num_frames_dropped(void) const
{
    return frames_dropped_;
}

//! Drop all buffers currently held by the decoder.
//!
//! This method forces the decoder to drop all buffers currently held either in the empty
//! buffer queue or currently mapped to incoming frames. It is intended to be used at
//! configuration time where, e.g. the underlying shared buffer manager has been reconfigured
//! and the current buffer references are thus invalid.
//!
void FrameDecoder::drop_all_buffers(void)
{
  if (!empty_buffer_queue_.empty())
  {
    LOG4CXX_INFO(logger_, "Dropping " << empty_buffer_queue_.size() 
        << " buffers from empty buffer queue");
    EmptyBufferQueue new_queue;
    std::swap(empty_buffer_queue_, new_queue);
  }

  if (!frame_buffer_map_.empty())
  {
    LOG4CXX_WARN(logger_, "Dropping " << frame_buffer_map_.size() <<
                 " unreleased buffers from decoder - possible data loss");
    FrameBufferMap new_map;
    std::swap(frame_buffer_map_, new_map);
  }
}

//! Collate version information for the decoder.
//!
//! The version information is added to the status IpcMessage object.
//! 
//! \param[in,out] status - Reference to an IpcMessage value to store the version.
//!
void FrameDecoder::version(const std::string param_prefix, OdinData::IpcMessage& status)
{
  status.set_param(param_prefix + "major", get_version_major());
  status.set_param(param_prefix + "minor", get_version_minor());
  status.set_param(param_prefix + "patch", get_version_patch());
  status.set_param(param_prefix + "short", get_version_short());
  status.set_param(param_prefix + "full", get_version_long());
}

//! Reset frame decoder statistics.
//!
//! This method resets the frame decoder statistics. In this base class this
//! is limited to setting the timed-out frames count to zero. Dervied decoder classes
//! which override this method should ensure the base class version is explicitly called.
//!
void FrameDecoder::reset_statistics(void)
{
    LOG4CXX_DEBUG_LEVEL(1, logger_, "Resetting frame decoder statistics");
    frames_timedout_ = 0;
    frames_dropped_ = 0;
}