1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  *  Copyright 2018. 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 #include <iomanip>
22 #include <sstream>
23 #include <ios>
24 
25 /**
26  * \file
27  * \ingroup mpi
28  *
29  * Common methods for MPI examples.
30  *
31  * Since MPI output is coming from multiple processors it is the
32  * ordering between the processors is non-deterministic.  For
33  * regression testing the output is sorted to force a deterministic
34  * ordering. Methods include here add line number to support
35  * this sorting.
36  *
37  * Testing output is also grepped so only lines with "TEST" are
38  * included.  Some MPI launchers emit extra text to output which must
39  * be excluded for regression comparisons.
40  */
41 
42 namespace ns3 {
43 
44 template <typename T> class Ptr;
45 class Address;
46 class Packet;
47 
48 
49 /**
50  * Write to std::cout only from rank 0.
51  * Number line for sorting output of parallel runs.
52  *
53  * \param x The output operators.
54  */
55 #define RANK0COUT(x)                                                                   \
56   do                                                                                   \
57     if (SinkTracer::GetWorldRank () == 0)                                              \
58       {                                                                                \
59         std::cout << "TEST : ";                                                        \
60         std::ios_base::fmtflags f( std::cout.flags() );                                \
61         std::cout << std::setfill('0') << std::setw(5) << SinkTracer::GetLineCount (); \
62         std::cout.flags( f );                                                          \
63         std::cout << " : " << x;                                                       \
64       }                                                                                \
65   while (false)
66 
67 #define RANK0COUTAPPEND(x)                      \
68   do                                            \
69     if (SinkTracer::GetWorldRank () == 0)       \
70       {                                         \
71         std::cout << x ;                        \
72       }                                         \
73   while (false)
74 
75 class SinkTracer
76 {
77 
78 public:
79   /**
80    * PacketSink receive trace callback.
81    * \copydetails ns3::Packet::TwoAddressTracedCallback
82    */
83   static void Init (void);
84 
85   /**
86    * PacketSink receive trace callback.
87    * \copydetails ns3::Packet::TwoAddressTracedCallback
88    */
89   static void SinkTrace (const ns3::Ptr<const ns3::Packet> packet,
90                          const ns3::Address &srcAddress,
91                          const ns3::Address &destAddress);
92 
93   /**
94    * Verify the sink trace count observed matches the expected count.
95    * Prints message to std::cout indicating success or fail.
96    */
97   static void Verify (unsigned long expectedCount);
98 
99   /**
100    * Get the source address and port, as a formatted string.
101    *
102    * \param [in] address The ns3::Address.
103    * \return A string with the formatted address and port number.
104    */
105   static std::string FormatAddress (const ns3::Address address);
106 
107   /**
108    * Get the MPI rank in the world communicator.
109    *
110    * \return MPI world rank.
111    */
GetWorldRank(void)112   static int GetWorldRank (void)
113   {
114     return m_worldRank;
115   }
116 
117   /**
118    * Get the MPI size of the world communicator.
119    *
120    * \return MPI world size.
121    */
GetWorldSize(void)122   static int GetWorldSize (void)
123   {
124     return m_worldSize;
125   }
126 
127   /**
128    * Get current line count and increment.
129    *
130    */
GetLineCount(void)131   static int GetLineCount (void)
132   {
133     return m_line++;
134   }
135 
136 private:
137   static unsigned long m_sinkCount; /*< Running sum of number of SinkTrace calls observed */
138   static unsigned long m_line; /*< Current output line number for ordering output */
139   static int m_worldRank; /*< MPI CommWorld rank */
140   static int m_worldSize; /*< MPI CommWorld size */
141 };
142 
143 }  // namespace ns3
144