EMANE  1.0.1
eeleventgenerator.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014,2016 - Adjacent Link LLC, Bridgewater, New
3  * Jersey
4  * Copyright (c) 2010-2012 - DRS CenGen, LLC, Columbia, Maryland
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  * * Neither the name of DRS CenGen, LLC nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  */
35 
36 #include "eeleventgenerator.h"
37 #include "eelinputparser.h"
38 
41 
43 
44 #include <sstream>
45 #include <fstream>
46 
48  EventGenerator(pPlatformService),
49  bCancel_{}
50 {}
51 
53 
55 {
56  auto & configRegistrar = registrar.configurationRegistrar();
57 
58  configRegistrar.registerNonNumeric<std::string>("inputfile",
60  {},
61  "EEL Text input file.",
62  1,
63  1024);
64 
65  configRegistrar.registerNonNumeric<std::string>("loader",
67  {},
68  "EEL Loader plugin.",
69  1,
70  1024);
71 }
72 
74 {
75  for(const auto & item : update)
76  {
77  if(item.first == "inputfile")
78  {
79  for(const auto & any : item.second)
80  {
81  std::string sInputFile = any.asString();
82 
84  INFO_LEVEL,
85  "EEL::Generator::start %s: %s",
86  item.first.c_str(),
87  sInputFile.c_str());
88 
89  inputFileNameVector_.push_back(sInputFile);
90  }
91  }
92  else if(item.first == "loader")
93  {
94  try
95  {
96  for(const auto & any : item.second)
97  {
98  std::string sLoaderPlugin = any.asString();
99 
100  size_t pos = sLoaderPlugin.find(':');
101 
102  if(pos != std::string::npos)
103  {
104  std::string sEventTypes = sLoaderPlugin.substr(0,pos);
105 
106  size_t pos2 = sLoaderPlugin.find(':',pos + 1);
107 
108  std::string sLibraryName = sLoaderPlugin.substr(pos + 1,pos2- pos -1);
109 
110  EventPublishMode publishMode = DELTA;
111 
112  if(pos2 != std::string::npos)
113  {
114  std::string sPublishMode = sLoaderPlugin.substr(pos2 + 1);
115 
116  if(sPublishMode == "delta")
117  {
118  publishMode = DELTA;
119  }
120  else if(sPublishMode == "full")
121  {
122  publishMode = FULL;
123  }
124  else
125  {
126  throw makeException<ConfigureException>("EEL::Generator: Unkown 'loader' "
127  "publish mode %s",
128  sPublishMode.c_str());
129  }
130  }
131 
132  LoaderPluginFactory * pPluginFactory = new LoaderPluginFactory();
133 
134  pPluginFactory->construct("lib" + sLibraryName + ".so");
135 
136  pluginFactoryList_.push_back(pPluginFactory);
137 
138  std::pair<LoaderPlugin *,EventPublishMode> loaderEntry =
139  std::make_pair(pPluginFactory->createPlugin(),publishMode);
140 
141  size_t pos1 = 0;
142 
143  pos2 = sLoaderPlugin.find(',');
144 
145  while(pos2 != std::string::npos)
146  {
147  std::string sEventType = sEventTypes.substr(pos1,pos2 - pos1);
148 
149  eventPluginMap_.insert(std::make_pair(sEventType,loaderEntry));
150 
152  INFO_LEVEL,
153  "EEL::Generator::configure %s: plugin %s will load %s sentences mode:%s",
154  item.first.c_str(),
155  sLoaderPlugin.c_str(),
156  sEventType.c_str(),
157  publishMode == DELTA ? "delta" : "full");
158  pos1 = pos2 + 1;
159 
160  pos2 = sEventTypes.find(',',pos1);
161  }
162 
163  std::string sEventType = sEventTypes.substr(pos1);
164 
165  eventPluginMap_.insert(std::make_pair(sEventType,loaderEntry));
166 
168  INFO_LEVEL,
169  "EEL::Generator::configure %s: plugin %s will load %s sentences mode:%s",
170  item.first.c_str(),
171  sLoaderPlugin.c_str(),
172  sEventType.c_str(),
173  publishMode == DELTA ? "delta" : "full");
174  }
175  else
176  {
177  throw makeException<ConfigureException>("EEL::Generator: Bad configuration 'loader' "
178  "format %s",
179  sLoaderPlugin.c_str());
180  }
181  }
182  }
183  catch(Utils::FactoryException & exp)
184  {
185  throw makeException<ConfigureException>("EEL::Generator: Factory exception %s",
186  exp.what());
187  }
188  }
189  else
190  {
191  throw makeException<ConfigureException>("EEL::Generator: "
192  "Unexpected configuration item %s",
193  item.first.c_str());
194  }
195  }
196 }
197 
199 {
200  thread_ = std::thread{&Generator::generate,this};
201 }
202 
204 {
205  if(thread_.joinable())
206  {
207  mutex_.lock();
208  bCancel_ = true;
209  cond_.notify_one();
210  mutex_.unlock();
211  thread_.join();
212  }
213 }
214 
216  throw()
217 {}
218 
219 void EMANE::Generators::EEL::Generator::generate()
220 {
221  char buf[2048];
222  float fCurrentTime = 0;
223  float fEventTime = 0;
224  unsigned long ulCurrentLine = 1;
225  InputParser parser;
226  InputFileNameVector::const_iterator iterFileName = inputFileNameVector_.begin();
227 
228  try
229  {
230  auto testStartTime = Clock::now();
231 
232  for(; iterFileName != inputFileNameVector_.end(); ++iterFileName)
233  {
234  std::ifstream eelInputStream;
235 
236  eelInputStream.open(iterFileName->c_str());
237 
238  if(!eelInputStream)
239  {
240  std::stringstream sstream;
241  sstream<<"EEL::Generator: Unable to open "<<*iterFileName<<std::ends;
242  throw FormatException(sstream.str());
243  }
244  else
245  {
247  DEBUG_LEVEL,
248  "EEL::Generator: Parsing %s",
249  iterFileName->c_str());
250 
251  ulCurrentLine = 1;
252  }
253 
254  // parse the next EEL entrty
255  while(eelInputStream.getline(buf,sizeof(buf)))
256  {
257  std::string sEventType;
258  std::string sModuleId;
259  InputArguments inputArguments;
260 
262 
263  if(parser.parse(std::string(buf),
264  fEventTime,
265  sEventType,
266  sModuleId,
267  inputArguments))
268  {
269  ModuleType sModuleType(sModuleId);
270  ModuleId u16ModuleId = 0;
271  size_t pos = sModuleId.find(':');
272 
273  if(pos != std::string::npos)
274  {
275  sModuleType = sModuleId.substr(0,pos);
276 
277  u16ModuleId =
278  Utils::ParameterConvert(sModuleId.substr(pos + 1)).toUINT16();
279  }
280 
281  if(fEventTime != fCurrentTime)
282  {
283  if(!waitAndSendEvents(testStartTime,fCurrentTime))
284  {
285  return;
286  }
287 
288  fCurrentTime = fEventTime;
289  }
290 
291  EventPluginMap::iterator iterPlugin;
292 
293  if((iterPlugin = eventPluginMap_.find(sEventType)) !=
294  eventPluginMap_.end())
295  {
297  DEBUG_LEVEL,
298  "Registered EEL event type '%s' at time %f for %s",
299  sEventType.c_str(),
300  fEventTime,
301  sModuleId.c_str());
302 
303  iterPlugin->second.first->load(sModuleType,
304  u16ModuleId,
305  sEventType,
306  inputArguments);
307  }
308  else
309  {
311  DEBUG_LEVEL,
312  "Unregistered EEL event type '%s' at time %f for %s",
313  sEventType.c_str(),
314  fEventTime,
315  sModuleId.c_str());
316  }
317  }
318 
319  ++ulCurrentLine;
320  }
321  }
322 
323  waitAndSendEvents(testStartTime,fCurrentTime);
324 
325  }
326  catch(Exception & exp)
327  {
329  ABORT_LEVEL,"%s (%s:%lu)",
330  exp.what(),
331  iterFileName->c_str(),
332  ulCurrentLine);
333  }
334 }
335 
336 bool EMANE::Generators::EEL::Generator::waitAndSendEvents(const TimePoint & testStartTime,
337  float fCurrentTime)
338 {
339  EventInfoList currentTimeEventList;
340 
341  EventPluginMap::iterator iterPlugin = eventPluginMap_.begin();
342 
343  for(;iterPlugin != eventPluginMap_.end(); ++iterPlugin)
344  {
345  EventInfoList eventList =
346  iterPlugin->second.first->getEvents(iterPlugin->second.second);
347 
348  currentTimeEventList.insert(currentTimeEventList.end(),
349  eventList.begin(),
350  eventList.end());
351  }
352 
353  // time to schedule the next event publications
354 
355  if(!currentTimeEventList.empty())
356  {
357  std::unique_lock<std::mutex> lock{mutex_};
358 
359  std::cv_status status{};
360 
361  while(!bCancel_ && status != std::cv_status::timeout)
362  {
363  status = cond_.wait_until(lock,
364  testStartTime +
365  DoubleSeconds{fCurrentTime});
366  }
367 
368  if(bCancel_)
369  {
370  return false;
371  }
372 
373  lock.unlock();
374 
376  DEBUG_LEVEL,
377  "Sending all events for time %f",
378  fCurrentTime);
379 
380  EventInfoList::iterator eventIter =
381  currentTimeEventList.begin();
382 
383  for(; eventIter != currentTimeEventList.end(); ++eventIter)
384  {
385  pPlatformService_->eventService().sendEvent(eventIter->getNEMId(),
386  eventIter->getEventId(),
387  eventIter->getSerialization());
388  }
389  }
390 
391  return true;
392 }
393 
The Registrar interface provides access to all of the emulator registrars.
Definition: registrar.h:50
std::vector< std::string > InputArguments
Factory for creating plugins . The factory manages the DLL allowing for the creation of plugins of th...
virtual ConfigurationRegistrar & configurationRegistrar()=0
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
void registerNonNumeric(const std::string &sName, const ConfigurationProperties &properties=ConfigurationProperties::NONE, const std::initializer_list< T > &values={}, const std::string &sUsage="", std::size_t minOccurs=1, std::size_t maxOccurs=1, const std::string &sRegexPattern={})
Exception base class that allows for type and description information.
Definition: exception.h:49
The PlatformServiceProvider interface provides access to emulator services.
Base class for all event generators.
bool parse(const std::string &sInput, float &fEventTime, std::string &sEventType, std::string &sModuleId, InputArguments &inputArguments)
virtual EventServiceProvider & eventService()=0
const char * what() const
Definition: exception.h:62
Exception thrown during the creation of a layer factory.
std::chrono::duration< double > DoubleSeconds
Definition: types.h:47
PlatformServiceProvider * pPlatformService_
Generator(PlatformServiceProvider *pPlatformService)
virtual LogServiceProvider & logService()=0
std::vector< ConfigurationNameAnyValues > ConfigurationUpdate
Clock::time_point TimePoint
Definition: types.h:50
void configure(const ConfigurationUpdate &update) override
#define LOGGER_STANDARD_LOGGING(logger, level, fmt, args...)
std::list< EventInfo > EventInfoList
virtual void sendEvent(NEMId nemId, const Event &event)=0
Parameter conversion class with range checks.
DECLARE_EVENT_GENERATOR(EMANE::Generators::EEL::Generator)
void initialize(Registrar &registrar) override