A Discrete-Event Network Simulator
API
null-message-simulator-impl.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright 2013. Lawrence Livermore National Security, LLC.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Steven Smith <smith84@llnl.gov>
19  *
20  */
21 
23 
26 #include "remote-channel-bundle.h"
27 #include "mpi-interface.h"
28 
29 #include <ns3/simulator.h>
30 #include <ns3/scheduler.h>
31 #include <ns3/event-impl.h>
32 #include <ns3/channel.h>
33 #include <ns3/node-container.h>
34 #include <ns3/double.h>
35 #include <ns3/ptr.h>
36 #include <ns3/pointer.h>
37 #include <ns3/assert.h>
38 #include <ns3/log.h>
39 
40 #include <cmath>
41 #include <iostream>
42 #include <fstream>
43 #include <iomanip>
44 
45 namespace ns3 {
46 
47 NS_LOG_COMPONENT_DEFINE ("NullMessageSimulatorImpl");
48 
49 NS_OBJECT_ENSURE_REGISTERED (NullMessageSimulatorImpl);
50 
51 NullMessageSimulatorImpl* NullMessageSimulatorImpl::g_instance = 0;
52 
53 TypeId
55 {
56  static TypeId tid = TypeId ("ns3::NullMessageSimulatorImpl")
58  .SetGroupName ("Mpi")
59  .AddConstructor<NullMessageSimulatorImpl> ()
60  .AddAttribute ("SchedulerTune", "Null Message scheduler tuning parameter",
61  DoubleValue (1.0),
63  MakeDoubleChecker<double> (0.01,1.0))
64  ;
65  return tid;
66 }
67 
69 {
70  NS_LOG_FUNCTION (this);
71 
74 
75  m_stop = false;
76  // uids are allocated from 4.
77  // uid 0 is "invalid" events
78  // uid 1 is "now" events
79  // uid 2 is "destroy" events
80  m_uid = 4;
81  // before ::Run is entered, the m_currentUid will be zero
82  m_currentUid = 0;
83  m_currentTs = 0;
86  m_eventCount = 0;
87  m_events = 0;
88 
89  m_safeTime = Seconds (0);
90 
91  NS_ASSERT (g_instance == 0);
92  g_instance = this;
93 }
94 
96 {
97  NS_LOG_FUNCTION (this);
98 }
99 
100 void
102 {
103  NS_LOG_FUNCTION (this);
104 
105  while (!m_events->IsEmpty ())
106  {
107  Scheduler::Event next = m_events->RemoveNext ();
108  next.impl->Unref ();
109  }
110  m_events = 0;
112 }
113 
114 void
116 {
117  NS_LOG_FUNCTION (this);
118 
119  while (!m_destroyEvents.empty ())
120  {
121  Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
122  m_destroyEvents.pop_front ();
123  NS_LOG_LOGIC ("handle destroy " << ev);
124  if (!ev->IsCancelled ())
125  {
126  ev->Invoke ();
127  }
128  }
129 
132 }
133 
134 void
136 {
137  NS_LOG_FUNCTION (this);
138 
139  int num_local_nodes = 0;
140 
141  if (MpiInterface::GetSize () > 1)
142  {
144  for (NodeContainer::Iterator iter = c.Begin (); iter != c.End (); ++iter)
145  {
146  if ((*iter)->GetSystemId () != MpiInterface::GetSystemId ())
147  {
148  continue;
149  }
150 
151  num_local_nodes++;
152 
153  for (uint32_t i = 0; i < (*iter)->GetNDevices (); ++i)
154  {
155  Ptr<NetDevice> localNetDevice = (*iter)->GetDevice (i);
156  // only works for p2p links currently
157  if (!localNetDevice->IsPointToPoint ())
158  {
159  continue;
160  }
161  Ptr<Channel> channel = localNetDevice->GetChannel ();
162  if (channel == 0)
163  {
164  continue;
165  }
166 
167  // grab the adjacent node
168  Ptr<Node> remoteNode;
169  if (channel->GetDevice (0) == localNetDevice)
170  {
171  remoteNode = (channel->GetDevice (1))->GetNode ();
172  }
173  else
174  {
175  remoteNode = (channel->GetDevice (0))->GetNode ();
176  }
177 
178  // if it's not remote, don't consider it
179  if (remoteNode->GetSystemId () == MpiInterface::GetSystemId ())
180  {
181  continue;
182  }
183 
187  Ptr<RemoteChannelBundle> remoteChannelBundle = RemoteChannelBundleManager::Find (remoteNode->GetSystemId ());
188  if (!remoteChannelBundle)
189  {
190  remoteChannelBundle = RemoteChannelBundleManager::Add (remoteNode->GetSystemId ());
191  }
192 
193  TimeValue delay;
194  channel->GetAttribute ("Delay", delay);
195  remoteChannelBundle->AddChannel (channel, delay.Get () );
196  }
197  }
198  }
199 
200  // Completed setup of remote channel bundles. Setup send and receive buffers.
202 
203  // Initialized to 0 as we don't have a simulation start time.
204  m_safeTime = Time (0);
205 }
206 
207 void
209 {
210  NS_LOG_FUNCTION (this << schedulerFactory);
211 
212  Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
213 
214  if (m_events != 0)
215  {
216  while (!m_events->IsEmpty ())
217  {
218  Scheduler::Event next = m_events->RemoveNext ();
219  scheduler->Insert (next);
220  }
221  }
222  m_events = scheduler;
223 }
224 
225 void
227 {
228  NS_LOG_FUNCTION (this);
229 
230  Scheduler::Event next = m_events->RemoveNext ();
231 
232  NS_ASSERT (next.key.m_ts >= m_currentTs);
234  m_eventCount++;
235 
236  NS_LOG_LOGIC ("handle " << next.key.m_ts);
237  m_currentTs = next.key.m_ts;
239  m_currentUid = next.key.m_uid;
240  next.impl->Invoke ();
241  next.impl->Unref ();
242 }
243 
244 bool
246 {
247  return m_events->IsEmpty () || m_stop;
248 }
249 
250 Time
252 {
253  NS_LOG_FUNCTION (this);
254 
255  NS_ASSERT (!m_events->IsEmpty ());
256 
257  Scheduler::Event ev = m_events->PeekNext ();
258  return TimeStep (ev.key.m_ts);
259 }
260 
261 void
263 {
264  NS_LOG_FUNCTION (this << bundle);
265 
266  Time delay (m_schedulerTune * bundle->GetDelay ().GetTimeStep ());
267 
269  this, PeekPointer(bundle)));
270 }
271 
272 void
274 {
275  NS_LOG_FUNCTION (this << bundle);
276 
277  Simulator::Cancel (bundle->GetEventId ());
278 
279  Time delay (m_schedulerTune * bundle->GetDelay ().GetTimeStep ());
280 
282  this, PeekPointer(bundle)));
283 }
284 
285 void
287 {
288  NS_LOG_FUNCTION (this << nodeSysId);
289 
291  NS_ASSERT (bundle);
292 
294 }
295 
296 void
298 {
299  NS_LOG_FUNCTION (this);
300 
302 
304 
305  // Stop will be set if stop is called by simulation.
306  m_stop = false;
307  while (!IsFinished ())
308  {
309  Time nextTime = Next ();
310 
311  if ( nextTime <= GetSafeTime () )
312  {
313  ProcessOneEvent ();
315  }
316  else
317  {
318  // Block until packet or Null Message has been received.
320  }
321  }
322 }
323 
324 void
326 {
327  NS_LOG_FUNCTION (this);
328 
330 
332 
333  // Check for send completes
335 }
336 
337 void
339 {
340  NS_LOG_FUNCTION (this);
341 
343 
345 
346  // Check for send completes
348 }
349 
350 void
352 {
353  NS_LOG_FUNCTION (this);
354 
357 }
358 
359 Time
361 {
362  return m_safeTime;
363 }
364 
365 
366 uint32_t
368 {
369  return m_myId;
370 }
371 
372 void
374 {
375  NS_LOG_FUNCTION (this);
376 
377  ProcessOneEvent ();
378 }
379 
380 void
382 {
383  NS_LOG_FUNCTION (this);
384 
385  m_stop = true;
386 }
387 
388 void
390 {
391  NS_LOG_FUNCTION (this << delay.GetTimeStep ());
392 
394 }
395 
396 //
397 // Schedule an event for a _relative_ time in the future.
398 //
399 EventId
401 {
402  NS_LOG_FUNCTION (this << delay.GetTimeStep () << event);
403 
404  Time tAbsolute = delay + TimeStep (m_currentTs);
405 
406  NS_ASSERT (tAbsolute.IsPositive ());
407  NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
408  Scheduler::Event ev;
409  ev.impl = event;
410  ev.key.m_ts = static_cast<uint64_t> (tAbsolute.GetTimeStep ());
411  ev.key.m_context = GetContext ();
412  ev.key.m_uid = m_uid;
413  m_uid++;
415  m_events->Insert (ev);
416  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
417 }
418 
419 void
420 NullMessageSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &delay, EventImpl *event)
421 {
422  NS_LOG_FUNCTION (this << context << delay.GetTimeStep () << m_currentTs << event);
423 
424  Time tAbsolute(m_currentTs + delay.GetTimeStep ());
425 
426  NS_ASSERT (tAbsolute.IsPositive ());
427  NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
428 
429  Scheduler::Event ev;
430  ev.impl = event;
431  ev.key.m_ts = tAbsolute.GetTimeStep ();
432  ev.key.m_context = context;
433  ev.key.m_uid = m_uid;
434  m_uid++;
436  m_events->Insert (ev);
437 }
438 
439 EventId
441 {
442  NS_LOG_FUNCTION (this << event);
443 
444  Scheduler::Event ev;
445  ev.impl = event;
446  ev.key.m_ts = m_currentTs;
447  ev.key.m_context = GetContext ();
448  ev.key.m_uid = m_uid;
449  m_uid++;
451  m_events->Insert (ev);
452  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
453 }
454 
455 EventId
457 {
458  NS_LOG_FUNCTION (this << event);
459 
460  EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
461  m_destroyEvents.push_back (id);
462  m_uid++;
463  return id;
464 }
465 
466 Time
468 {
469  return TimeStep (m_currentTs);
470 }
471 
472 Time
474 {
475  if (IsExpired (id))
476  {
477  return TimeStep (0);
478  }
479  else
480  {
481  return TimeStep (id.GetTs () - m_currentTs);
482  }
483 }
484 
485 void
487 {
488  if (id.GetUid () == 2)
489  {
490  // destroy events.
491  for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
492  {
493  if (*i == id)
494  {
495  m_destroyEvents.erase (i);
496  break;
497  }
498  }
499  return;
500  }
501  if (IsExpired (id))
502  {
503  return;
504  }
505  Scheduler::Event event;
506  event.impl = id.PeekEventImpl ();
507  event.key.m_ts = id.GetTs ();
508  event.key.m_context = id.GetContext ();
509  event.key.m_uid = id.GetUid ();
510  m_events->Remove (event);
511  event.impl->Cancel ();
512  // whenever we remove an event from the event list, we have to unref it.
513  event.impl->Unref ();
514 
516 }
517 
518 void
520 {
521  if (!IsExpired (id))
522  {
523  id.PeekEventImpl ()->Cancel ();
524  }
525 }
526 
527 bool
529 {
530  if (id.GetUid () == 2)
531  {
532  if (id.PeekEventImpl () == 0
533  || id.PeekEventImpl ()->IsCancelled ())
534  {
535  return true;
536  }
537  // destroy events.
538  for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
539  {
540  if (*i == id)
541  {
542  return false;
543  }
544  }
545  return true;
546  }
547  if (id.PeekEventImpl () == 0
548  || id.GetTs () < m_currentTs
549  || (id.GetTs () == m_currentTs
550  && id.GetUid () <= m_currentUid)
551  || id.PeekEventImpl ()->IsCancelled ())
552  {
553  return true;
554  }
555  else
556  {
557  return false;
558  }
559 }
560 
561 Time
563 {
564  // XXX: I am fairly certain other compilers use other non-standard
565  // post-fixes to indicate 64 bit constants.
566  return TimeStep (0x7fffffffffffffffLL);
567 }
568 
569 uint32_t
571 {
572  return m_currentContext;
573 }
574 
575 uint64_t
577 {
578  return m_eventCount;
579 }
580 
582 {
584  NS_ASSERT (bundle);
585 
586  return Min (NullMessageSimulatorImpl::GetInstance ()->Next (), GetSafeTime ()) + bundle->GetDelay ();
587 }
588 
590 {
591  NS_LOG_FUNCTION (this << bundle);
592 
593  Time time = Min (Next (), GetSafeTime ()) + bundle->GetDelay ();
595 
596  ScheduleNullMessageEvent (bundle);
597 }
598 
599 
602 {
603  NS_ASSERT (g_instance != 0);
604  return g_instance;
605 }
606 } // namespace ns3
607 
Time CalculateGuaranteeTime(uint32_t systemId)
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
virtual void Remove(const EventId &id)
Remove an event from the event list.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void Unref(void) const
Decrement the reference count.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
virtual void Destroy()
Execute the events scheduled with ScheduleDestroy().
uint64_t m_ts
Event time stamp.
Definition: scheduler.h:170
void HandleArrivingMessagesNonBlocking(void)
Non blocking receive of pending messages.
virtual EventId ScheduleNow(EventImpl *event)
Schedule an event to run at the current virtual time.
EventImpl * impl
Pointer to the event implementation.
Definition: scheduler.h:183
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:411
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
virtual bool IsFinished(void) const
Check if the simulation should finish.
static void ReceiveMessagesNonBlocking()
Non-blocking check for received messages complete.
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event&#39;s associated function will not be invoked when it expires...
Definition: simulator.cc:268
void ProcessOneEvent(void)
Process the next event on the queue.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:743
void RescheduleNullMessageEvent(Ptr< RemoteChannelBundle > bundle)
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
Collection of NS3 channels between local and remote nodes.
Iterator End(void) const
Get an iterator which indicates past-the-last Node in the container.
virtual EventId ScheduleDestroy(EventImpl *event)
Schedule an event to run at the end of the simulation, after the Stop() time or condition has been re...
virtual uint32_t GetContext(void) const
Get the current simulation context.
channel
Definition: third.py:92
void CalculateSafeTime(void)
Calculate the SafeTime.
void Invoke(void)
Called by the simulation engine to notify the event that it is time to execute.
Definition: event-impl.cc:46
static NullMessageSimulatorImpl * GetInstance(void)
static void TestSendComplete()
Check for completed sends.
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:218
EventKey key
Key for sorting and ordering Events.
Definition: scheduler.h:184
static void Destroy()
Deletes storage used by the parallel environment.
AttributeValue implementation for Time.
Definition: nstime.h:1124
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
uint32_t m_uid
Event unique id.
Definition: scheduler.h:171
static void SendNullMessage(const Time &guaranteeUpdate, Ptr< RemoteChannelBundle > bundle)
Send a Null Message to across the specified bundle.
static void InitializeNullMessageEvents(void)
Setup initial Null Message events for every RemoteChannelBundle.
Time GetSafeTime(void)
Get the current SafeTime; the maximum time that events can be processed based on information received...
Maintain the event list.
Definition: scheduler.h:155
virtual uint64_t GetEventCount(void) const
Get the number of events executed.
static void Destroy(void)
Destroy the singleton.
virtual void Run(void)
Run the simulation.
static NullMessageSimulatorImpl * g_instance
virtual bool IsExpired(const EventId &id) const
Check if an event has already run or been cancelled.
Scheduler event.
Definition: scheduler.h:181
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void CalculateLookAhead(void)
Calculate the look ahead allowable for this MPI task.
keep track of a set of node pointers.
static void ReceiveMessagesBlocking()
Blocking message receive.
virtual void ScheduleWithContext(uint32_t context, Time const &delay, EventImpl *event)
Schedule a future event execution (in a different context).
uint32_t GetSystemId(void) const
Definition: node.cc:123
static Ptr< RemoteChannelBundle > Find(uint32_t systemId)
void HandleArrivingMessagesBlocking(void)
Blocking receive of arriving messages.
virtual Time Now(void) const
Return the current simulation virtual time.
Time TimeStep(uint64_t ts)
Definition: nstime.h:1119
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
static Ptr< RemoteChannelBundle > Add(uint32_t systemId)
Add RemoteChannelBundle from this task to MPI task on other side of the link.
Simulator implementation using MPI and a Null Message algorithm.
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
static NodeContainer GetGlobal(void)
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
Instantiate subclasses of ns3::Object.
A simulation event.
Definition: event-impl.h:44
virtual uint32_t GetSystemId(void) const
Get the system id of this simulator.
An identifier for simulation events.
Definition: event-id.h:53
static uint32_t GetSystemId()
virtual Time GetMaximumSimulationTime(void) const
Get the maximum representable simulation time.
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
Time Get(void) const
Definition: time.cc:446
virtual void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1062
virtual void Cancel(const EventId &id)
Set the cancel bit on this event: the event&#39;s associated function will not be invoked when it expires...
void ScheduleNullMessageEvent(Ptr< RemoteChannelBundle > bundle)
Flag for events not associated with any particular context.
Definition: simulator.h:199
void NullMessageEventHandler(RemoteChannelBundle *bundle)
virtual EventId Schedule(Time const &delay, EventImpl *event)
Schedule a future event execution (in the same context).
virtual void DoDispose(void)
Destructor implementation.
static void InitializeSendReceiveBuffers(void)
Initialize send and receive buffers.
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
a unique identifier for an interface.
Definition: type-id.h:58
virtual void SetScheduler(ObjectFactory schedulerFactory)
Set the Scheduler to be used to manage the event list.
virtual Time GetDelayLeft(const EventId &id) const
Get the remaining time until this event will execute.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
static uint32_t GetSize()
uint32_t m_context
Event context.
Definition: scheduler.h:172
Iterator Begin(void) const
Get an iterator which refers to the first Node in the container.
The SimulatorImpl base class.
int64_t GetTimeStep(void) const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:397