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