artdaq_demo  v3_06_01
AsciiSimulator_generator.cc
1 #include "artdaq-demo/Generators/AsciiSimulator.hh"
2 
3 #include "canvas/Utilities/Exception.h"
4 
5 #include "artdaq-core-demo/Overlays/AsciiFragment.hh"
6 #include "artdaq-core-demo/Overlays/AsciiFragmentWriter.hh"
7 #include "artdaq-core-demo/Overlays/FragmentType.hh"
8 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
9 #include "artdaq/Generators/GeneratorMacros.hh"
10 #include "cetlib_except/exception.h"
11 #include "fhiclcpp/ParameterSet.h"
12 
13 #include <fstream>
14 #include <iomanip>
15 #include <iostream>
16 #include <iterator>
17 
18 #include <unistd.h>
19 
20 namespace {
27 template<typename T>
28 T convertToASCII( std::string input )
29 {
30  if ( input.size() < sizeof( T ) / sizeof( char ) )
31  { input.insert( 0, sizeof( T ) / sizeof( char ) - input.size(), ' ' ); }
32  else if ( input.size() > sizeof( T ) / sizeof( char ) )
33  {
34  input.erase( 0, input.size() - sizeof( T ) / sizeof( char ) );
35  }
36 
37  uint64_t bigOutput = 0ull;
38  // std::ofstream outputStr ("/tmp/ASCIIConverter.bin", std::ios::out | std::ios::app | std::ios::binary );
39  for ( uint i = 0; i < input.length(); ++i )
40  {
41  // outputStr.write((char*)&input[i],sizeof(char));
42  bigOutput *= 0x100;
43  bigOutput += input[ input.length() - i - 1 ];
44  }
45 
46  // outputStr.close();
47  return static_cast<T>( bigOutput );
48 }
49 } // namespace
50 
51 demo::AsciiSimulator::AsciiSimulator( fhicl::ParameterSet const& ps )
52  : CommandableFragmentGenerator( ps )
53  , throttle_usecs_( ps.get<size_t>( "throttle_usecs", 100000 ) )
54  , string1_( ps.get<std::string>( "string1", "All work and no play makes ARTDAQ a dull library" ) )
55  , string2_( ps.get<std::string>( "string2", "Hey, look at what ARTDAQ can do!" ) )
56 {}
57 
58 bool demo::AsciiSimulator::getNext_( artdaq::FragmentPtrs& frags )
59 {
60  // JCF, 9/23/14
61 
62  // If throttle_usecs_ is greater than zero (i.e., user requests a
63  // sleep interval before generating the pseudodata) then during that
64  // interval perform a periodic check to see whether a stop request
65  // has been received
66 
67  // Values for throttle_usecs_ and throttle_usecs_check_ will have
68  // been tested for validity in constructor
69 
70  if ( throttle_usecs_ > 0 )
71  {
72  size_t nchecks = throttle_usecs_ / 10000;
73 
74  for ( size_t i_c = 0; i_c < nchecks; ++i_c )
75  {
76  usleep( throttle_usecs_ / 10000 );
77 
78  if ( should_stop() ) { return false; }
79  }
80  }
81  else
82  {
83  if ( should_stop() ) { return false; }
84  }
85 
86  // Set fragment's metadata
87  size_t data_size = ev_counter() % 2 ? string1_.length() + 2 : string2_.length() + 2;
88  AsciiFragment::Metadata metadata;
89  std::string size_string = "S:" + std::to_string( data_size ) + ",";
90  metadata.charsInLine = convertToASCII<AsciiFragment::Metadata::chars_in_line_t>( size_string );
91 
92  // And use it, along with the artdaq::Fragment header information
93  // (fragment id, sequence id, and user type) to create a fragment
94 
95  // We'll use the static factory function
96 
97  // artdaq::Fragment::FragmentBytes(std::size_t payload_size_in_bytes, sequence_id_t sequence_id,
98  // fragment_id_t fragment_id, type_t type, const T & metadata)
99 
100  // which will then return a unique_ptr to an artdaq::Fragment
101  // object. The advantage of this approach over using the
102  // artdaq::Fragment constructor is that, if we were to want to
103  // initialize the artdaq::Fragment with a nonzero-size payload (data
104  // after the artdaq::Fragment header and metadata), we could provide
105  // the size of the payload in bytes, rather than in units of the
106  // artdaq::Fragment's RawDataType (8 bytes, as of 3/26/14). The
107  // artdaq::Fragment constructor itself was not altered so as to
108  // maintain backward compatibility.
109 
110  std::size_t initial_payload_size = 0;
111 
112  std::unique_ptr<artdaq::Fragment> fragptr( artdaq::Fragment::FragmentBytes(
113  initial_payload_size, ev_counter(), fragment_id(), FragmentType::ASCII, metadata ) );
114  frags.emplace_back( std::move( fragptr ) );
115 
116  // Then any overlay-specific quantities next; will need the
117  // AsciiFragmentWriter class's setter-functions for this
118 
119  AsciiFragmentWriter newfrag( *frags.back() );
120 
121  newfrag.set_hdr_line_number(
122  convertToASCII<AsciiFragment::Header::line_number_t>( "LN:" + std::to_string( ev_counter() ) + "," ) );
123 
124  newfrag.resize( data_size );
125 
126  // Now, generate the payload, based on the string to use
127  std::string string_to_use = ev_counter() % 2 ? string1_ : string2_;
128  string_to_use += "\r\n";
129 
130  // std::ofstream output ("/tmp/ASCIIGenerator.bin", std::ios::out | std::ios::app | std::ios::binary );
131  for ( uint i = 0; i < string_to_use.length(); ++i )
132  {
133  // output.write((char*)&string_to_use[i],sizeof(char));
134  *( newfrag.dataBegin() + i ) = string_to_use[ i ];
135  }
136  // output.close();
137 
138  ev_counter_inc();
139 
140  return true;
141 }
142 
143 // The following macro is defined in artdaq's GeneratorMacros.hh header
144 DEFINE_ARTDAQ_COMMANDABLE_GENERATOR( demo::AsciiSimulator )
Generates ASCIIFragments filled with user-specified ASCII strings.
AsciiSimulator(fhicl::ParameterSet const &ps)
AsciiSimulator Constructor.
T convertToASCII(std::string input)
Convert sizeof(T) characters of a string to a number containing the ASCII representation of that stri...