Psyllid  v1.12.4
Project 8 Data Acquisisition Software
butterfly_house.cc
Go to the documentation of this file.
1 /*
2  * butterfly_house.cc
3  *
4  * Created on: Feb 11, 2016
5  * Author: nsoblath
6  */
7 
8 #include "butterfly_house.hh"
9 
10 #include "daq_control.hh"
11 #include "egg_writer.hh"
12 
13 #include "logger.hh"
14 #include "param.hh"
15 #include "time.hh"
16 
17 #include "psyllid_error.hh"
18 
19 namespace psyllid
20 {
21  LOGGER( plog, "butterfly_house" );
22 
23 
26  f_max_file_size_mb( 500 ),
27  f_file_infos(),
28  f_mw_ptrs(),
29  f_writers(),
30  f_house_mutex()
31  {
32  LDEBUG( plog, "Butterfly house has been built" );
33  }
34 
36  {
37  }
38 
39 
40  void butterfly_house::prepare_files( const scarab::param_node& a_daq_config )
41  {
42  std::unique_lock< std::mutex > t_lock( f_house_mutex );
43 
44  // default is 1 file
45  f_file_infos.clear();
46 
47  if( a_daq_config.empty() )
48  {
49  f_file_infos.resize( 1 );
50  }
51  else
52  {
53  f_file_infos.resize( a_daq_config.get_value( "n-files", 1U ) );
54  set_max_file_size_mb( a_daq_config.get_value( "max-file-size-mb", get_max_file_size_mb() ) );
55  }
56 
57  for( file_infos_it fi_it = f_file_infos.begin(); fi_it != f_file_infos.end(); ++fi_it )
58  {
59  // creating default filenames; these can be changed when the run is started
60  std::stringstream t_filename_sstr;
61  unsigned t_file_num = fi_it - f_file_infos.begin();
62  t_filename_sstr << "psyllid_out_" << t_file_num << ".egg";
63  fi_it->f_filename = t_filename_sstr.str();
64  fi_it->f_description = "";
65  LPROG( plog, "Prepared file <" << t_file_num << ">; default filename is <" << fi_it->f_filename << ">" );
66  }
67  return;
68  }
69 
71  {
72  std::unique_lock< std::mutex > t_lock( f_house_mutex );
73 
75  {
76  LERROR( plog, "Unable to get access to the DAQ control" );
77  throw error() << "Butterfly house is unable to get access to the DAQ control";
78  }
79  unsigned t_run_duration = use_daq_control()->get_run_duration();
80 
81  LINFO( plog, "Starting egg3 files" );
82  try
83  {
84  f_mw_ptrs.clear();
85  f_mw_ptrs.resize( f_file_infos.size() );
86  for( unsigned t_file_num = 0; t_file_num < f_file_infos.size(); ++t_file_num )
87  {
88  std::string t_filename( f_file_infos[ t_file_num ].f_filename );
89  LDEBUG( plog, "Creating file <" << t_filename << ">" );
90  f_mw_ptrs[ t_file_num ] = monarch_wrap_ptr( new monarch_wrapper( t_filename ) );
91  f_mw_ptrs[ t_file_num ]->set_max_file_size( f_max_file_size_mb );
92 
93  header_wrap_ptr t_hwrap_ptr = f_mw_ptrs[ t_file_num ]->get_header();
94  unique_lock t_header_lock( t_hwrap_ptr->get_lock() );
95  t_hwrap_ptr->header().Description() = f_file_infos[ t_file_num ].f_description;
96 
97  time_t t_raw_time = time( nullptr );
98  struct tm* t_processed_time = gmtime( &t_raw_time );
99  char t_timestamp[ 512 ];
100  strftime( t_timestamp, 512, scarab::date_time_format, t_processed_time );
101  //LWARN( plog, "raw: " << t_raw_time << " proc'd: " << t_processed_time->tm_hour << " " << t_processed_time->tm_min << " " << t_processed_time->tm_year << " timestamp: " << t_timestamp );
102  t_hwrap_ptr->header().Timestamp() = t_timestamp;
103 
104  t_hwrap_ptr->header().SetRunDuration( t_run_duration );
105 
106  // writer/stream setup
107  LDEBUG( plog, "Setting up streams" );
108  for( auto it_writer = f_writers.begin(); it_writer != f_writers.end(); ++it_writer )
109  {
110  if( it_writer->second == t_file_num )
111  {
112  it_writer->first->prepare_to_write( f_mw_ptrs[ t_file_num ], t_hwrap_ptr );
113  }
114  }
115 
116  // be sure to unlock here; the header mutex is locked again in monarch_wrapper::start_using()
117  t_header_lock.unlock();
118 
119  f_mw_ptrs[ t_file_num ]->start_using();
120  }
121  LINFO( plog, "Done creating egg3 files" );
122  }
123  catch( std::exception& e )
124  {
125  throw;
126  }
127 
128  return;
129  }
130 
132  {
133  std::unique_lock< std::mutex > t_lock( f_house_mutex );
134  try
135  {
136  for( auto file_it = f_mw_ptrs.begin(); file_it != f_mw_ptrs.end(); ++file_it )
137  {
138  (*file_it)->cancel();
139  (*file_it)->stop_using();
140  (*file_it)->finish_file();
141  file_it->reset();
142  }
143  f_mw_ptrs.clear();
144  }
145  catch( std::exception& e )
146  {
147  throw;
148  }
149 
150  return;
151  }
152 
153  void butterfly_house::register_writer( egg_writer* a_writer, unsigned a_file_num )
154  {
155  std::unique_lock< std::mutex > t_lock( f_house_mutex );
156 
157  if( a_file_num >= f_file_infos.size() )
158  {
159  throw error() << "Currently configured number of files is <" << f_file_infos.size() << ">, but file <" << a_file_num << "> was requested by a writer; please reconfigure for the appropriate number of files or assign the writer to the appropriate file number.";
160  }
161 
162  bool t_has_already = false;
163  auto t_range = f_writers.equal_range( a_writer );
164  for( auto t_it = t_range.first; t_it != t_range.second; ++t_it )
165  {
166  if( t_it->second == a_file_num )
167  {
168  t_has_already = true;
169  break;
170  }
171  }
172  if( t_has_already )
173  {
174  throw error() << "Egg writer at <" << a_writer << "> is already registered for file number " << a_file_num;
175  }
176  f_writers.insert( std::pair< egg_writer*, unsigned >( a_writer, a_file_num ) );
177  return;
178  }
179 
181  {
182  std::unique_lock< std::mutex > t_lock( f_house_mutex );
183  auto t_range = f_writers.equal_range( a_writer );
184  f_writers.erase( t_range.first, t_range.second );
185  return;
186  }
187 
188  void butterfly_house::set_filename( const std::string& a_filename, unsigned a_file_num )
189  {
190  std::unique_lock< std::mutex > t_lock( f_house_mutex );
191  if( a_file_num > f_file_infos.size() ) throw error() << "Currently configured number of files is <" << f_file_infos.size() << ">, but filename-set was for file <" << a_file_num << ">.";
192  f_file_infos[ a_file_num ].f_filename = a_filename;
193  return;
194  }
195 
196  const std::string& butterfly_house::get_filename( unsigned a_file_num )
197  {
198  std::unique_lock< std::mutex > t_lock( f_house_mutex );
199  if( a_file_num > f_file_infos.size() ) throw error() << "Currently configured number of files is <" << f_file_infos.size() << ">, but filename-get was for file <" << a_file_num << ">.";
200  return f_file_infos[ a_file_num ].f_filename;
201  }
202 
203  void butterfly_house::set_description( const std::string& a_desc, unsigned a_file_num )
204  {
205  std::unique_lock< std::mutex > t_lock( f_house_mutex );
206  if( a_file_num > f_file_infos.size() ) throw error() << "Currently configured number of files is <" << f_file_infos.size() << ">, but description-set was for file <" << a_file_num << ">.";
207  f_file_infos[ a_file_num ].f_description = a_desc;
208  return;
209  }
210 
211  const std::string& butterfly_house::get_description( unsigned a_file_num )
212  {
213  std::unique_lock< std::mutex > t_lock( f_house_mutex );
214  if( a_file_num > f_file_infos.size() ) throw error() << "Currently configured number of files is <" << f_file_infos.size() << ">, but description-get was for file <" << a_file_num << ">.";
215  return f_file_infos[ a_file_num ].f_description;
216  }
217 
218 } /* namespace psyllid */
std::shared_ptr< header_wrapper > header_wrap_ptr
Base class for all writers.
Definition: egg_writer.hh:24
const std::string & get_filename(unsigned a_file_num)
void register_writer(egg_writer *a_writer, unsigned a_file_num)
static scarab::logger plog("batch_executor")
void unregister_writer(egg_writer *a_writer)
std::unique_lock< std::mutex > unique_lock
void set_filename(const std::string &a_filename, unsigned a_file_num=0)
void prepare_files(const scarab::param_node &a_files_config)
Gives other classes access to daq_control.
const std::string & get_description(unsigned a_file_num)
std::shared_ptr< monarch_wrapper > monarch_wrap_ptr
LOGGER(plog, "egg_writer")
std::vector< monarch_wrap_ptr > f_mw_ptrs
Wrapper class for a monarch3::M3Monarch object.
void set_description(const std::string &a_desc, unsigned a_file_num=0)
std::multimap< egg_writer *, unsigned > f_writers
file_infos_t::iterator file_infos_it