1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/examples/names.cc Tue Jan 20 15:47:14 2009 -0800
1.3 @@ -0,0 +1,142 @@
1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
1.5 +/*
1.6 + * This program is free software; you can redistribute it and/or modify
1.7 + * it under the terms of the GNU General Public License version 2 as
1.8 + * published by the Free Software Foundation;
1.9 + *
1.10 + * This program is distributed in the hope that it will be useful,
1.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.13 + * GNU General Public License for more details.
1.14 + *
1.15 + * You should have received a copy of the GNU General Public License
1.16 + * along with this program; if not, write to the Free Software
1.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.18 + */
1.19 +
1.20 +// Network topology
1.21 +//
1.22 +// n0 n1 n2 n3
1.23 +// | | | |
1.24 +// =================
1.25 +// LAN
1.26 +//
1.27 +
1.28 +#include <fstream>
1.29 +#include "ns3/core-module.h"
1.30 +#include "ns3/simulator-module.h"
1.31 +#include "ns3/helper-module.h"
1.32 +
1.33 +using namespace ns3;
1.34 +
1.35 +NS_LOG_COMPONENT_DEFINE ("NamesExample");
1.36 +
1.37 +void
1.38 +RxEvent (std::string context, Ptr<const Packet> packet)
1.39 +{
1.40 + NS_LOG_INFO (context << " packet " << packet);
1.41 +}
1.42 +
1.43 +int
1.44 +main (int argc, char *argv[])
1.45 +{
1.46 + //
1.47 + // Users may find it convenient to turn on explicit debugging
1.48 + // for selected modules; the below lines suggest how to do this
1.49 + //
1.50 +#if 1
1.51 + LogComponentEnable ("NamesExample", LOG_LEVEL_INFO);
1.52 +#endif
1.53 +
1.54 + //
1.55 + // Allow the user to override any of the defaults and the above Bind() at
1.56 + // run-time, via command-line arguments
1.57 + //
1.58 + CommandLine cmd;
1.59 + cmd.Parse (argc, argv);
1.60 +
1.61 + //
1.62 + // Explicitly create the nodes required by the topology (shown above).
1.63 + //
1.64 + NS_LOG_INFO ("Create nodes.");
1.65 + NodeContainer n;
1.66 + n.Create (4);
1.67 +
1.68 + //
1.69 + // We're going to use the zeroth node in the container as the client, and
1.70 + // the first node as the server. Add some "human readable" names for these
1.71 + // nodes. The first parameter specifies the root of the "/Names" name space
1.72 + // as the destination, so these will go into the name system as "/Names/client"
1.73 + // and "/Names/server".
1.74 + //
1.75 + Names::Add ("/Names", "client", n.Get (0));
1.76 + Names::Add ("/Names", "server", n.Get (1));
1.77 +
1.78 + InternetStackHelper internet;
1.79 + internet.Install (n);
1.80 +
1.81 + NS_LOG_INFO ("Create devices.");
1.82 + CsmaHelper csma;
1.83 + csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000)));
1.84 + csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
1.85 + csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
1.86 + NetDeviceContainer d = csma.Install (n);
1.87 +
1.88 + //
1.89 + // Add some human readable names for the devices we'll be interested in.
1.90 + // We add the names to the name space "under" the nodes we created above.
1.91 + // This has the effect of making "/Names/client/eth0" and "/Names/server/eth0"
1.92 + // Note that the first parameter must reference a previously named object,
1.93 + // and we have, in fact, already named objects "/Names/client" and
1.94 + // "/Names/server"
1.95 + //
1.96 + Names::Add ("/Names/client", "eth0", d.Get (0));
1.97 + Names::Add ("/Names/server", "eth0", d.Get (1));
1.98 +
1.99 + Ipv4AddressHelper ipv4;
1.100 +
1.101 + //
1.102 + // We've got the "hardware" in place. Now we need to add IP addresses.
1.103 + //
1.104 + NS_LOG_INFO ("Assign IP Addresses.");
1.105 + ipv4.SetBase ("10.1.1.0", "255.255.255.0");
1.106 + Ipv4InterfaceContainer i = ipv4.Assign (d);
1.107 +
1.108 + NS_LOG_INFO ("Create Applications.");
1.109 +
1.110 + //
1.111 + // Create a UdpEchoServer application on the server node. Note that we
1.112 + // reference the server node by name in the Install method below.
1.113 + //
1.114 + uint16_t port = 9; // well-known echo port number
1.115 + UdpEchoServerHelper server (port);
1.116 + ApplicationContainer apps = server.Install (Names::Find<Node> ("/Names/server"));
1.117 + apps.Start (Seconds (1.0));
1.118 + apps.Stop (Seconds (10.0));
1.119 +
1.120 + //
1.121 + // Create a UdpEchoClient application to send UDP datagrams from node zero to
1.122 + // node one. Notice that we reference the client node by name in the Install
1.123 + // method below.
1.124 + //
1.125 + uint32_t packetSize = 1024;
1.126 + uint32_t maxPacketCount = 1;
1.127 + Time interPacketInterval = Seconds (1.);
1.128 + UdpEchoClientHelper client (i.GetAddress (1), port);
1.129 + client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
1.130 + client.SetAttribute ("Interval", TimeValue (interPacketInterval));
1.131 + client.SetAttribute ("PacketSize", UintegerValue (packetSize));
1.132 + apps = client.Install (Names::Find<Node> ("/Names/client"));
1.133 + apps.Start (Seconds (2.0));
1.134 + apps.Stop (Seconds (10.0));
1.135 +
1.136 + Config::Connect ("/Names/client/eth0/Rx", MakeCallback (&RxEvent));
1.137 +
1.138 + //
1.139 + // Now, do the actual simulation.
1.140 + //
1.141 + NS_LOG_INFO ("Run Simulation.");
1.142 + Simulator::Run ();
1.143 + Simulator::Destroy ();
1.144 + NS_LOG_INFO ("Done.");
1.145 +}
2.1 --- a/examples/wscript Sun Jan 18 22:47:25 2009 +0000
2.2 +++ b/examples/wscript Tue Jan 20 15:47:14 2009 -0800
2.3 @@ -16,6 +16,10 @@
2.4 ['core', 'simulator', 'point-to-point', 'csma', 'wifi', 'internet-stack'])
2.5 obj.source = 'third.cc'
2.6
2.7 + obj = bld.create_ns3_program('names',
2.8 + ['core', 'simulator', 'csma', 'internet-stack'])
2.9 + obj.source = 'names.cc'
2.10 +
2.11 obj = bld.create_ns3_program('mixed-wireless',
2.12 ['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-stack'])
2.13 obj.source = 'mixed-wireless.cc'
3.1 --- a/src/core/config.cc Sun Jan 18 22:47:25 2009 +0000
3.2 +++ b/src/core/config.cc Tue Jan 20 15:47:14 2009 -0800
3.3 @@ -22,6 +22,7 @@
3.4 #include "object.h"
3.5 #include "global-value.h"
3.6 #include "object-vector.h"
3.7 +#include "object-names.h"
3.8 #include "pointer.h"
3.9 #include "log.h"
3.10 #include <sstream>
3.11 @@ -294,6 +295,45 @@
3.12 std::string item = path.substr (1, next-1);
3.13 std::string pathLeft = path.substr (next, path.size ()-next);
3.14
3.15 + //
3.16 + // If root is zero, we're beginning to see if we can use the object name
3.17 + // service to resolve this path. In this case, we must see the name space
3.18 + // "/Names" on the front of this path. There is no object associated with
3.19 + // the root of the "/Names" namespace, so we just ignore it and move on to
3.20 + // the next segment.
3.21 + //
3.22 + if (root == 0)
3.23 + {
3.24 + std::string::size_type offset = path.find ("/Names");
3.25 + if (offset == 0)
3.26 + {
3.27 + m_workStack.push_back (item);
3.28 + DoResolve (pathLeft, root);
3.29 + m_workStack.pop_back ();
3.30 + return;
3.31 + }
3.32 + }
3.33 +
3.34 + //
3.35 + // We have an item (possibly a segment of a namespace path. Check to see if
3.36 + // we can determine that this segment refers to a named object. If root is
3.37 + // zero, this means to look in the root of the "/Names" name space, otherwise
3.38 + // it refers to a name space context (level).
3.39 + //
3.40 + Ptr<Object> namedObject = Names::FindObjectFromShortName<Object> (root, item);
3.41 + if (namedObject)
3.42 + {
3.43 + NS_LOG_DEBUG ("Name system resolved item = " << item << " to " << namedObject);
3.44 + m_workStack.push_back (item);
3.45 + DoResolve (pathLeft, namedObject);
3.46 + m_workStack.pop_back ();
3.47 + return;
3.48 + }
3.49 +
3.50 + //
3.51 + // We're done with the object name service hooks, so proceed down the path
3.52 + // of types and attributes.
3.53 + //
3.54 std::string::size_type dollarPos = item.find ("$");
3.55 if (dollarPos == 0)
3.56 {
3.57 @@ -480,6 +520,14 @@
3.58 {
3.59 resolver.Resolve (*i);
3.60 }
3.61 +
3.62 + //
3.63 + // See if we can do something with the object name service. Starting with
3.64 + // the root pointer zeroed indicates to the resolver that it should start
3.65 + // looking at the root of the "/Names" namespace during this go.
3.66 + //
3.67 + resolver.Resolve (0);
3.68 +
3.69 return Config::MatchContainer (resolver.m_objects, resolver.m_contexts, path);
3.70 }
3.71
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/src/core/object-names.cc Tue Jan 20 15:47:14 2009 -0800
4.3 @@ -0,0 +1,624 @@
4.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
4.5 +/*
4.6 + * Copyright (c) 2009 University of Washington
4.7 + *
4.8 + * This program is free software; you can redistribute it and/or modify
4.9 + * it under the terms of the GNU General Public License version 2 as
4.10 + * published by the Free Software Foundation;
4.11 + *
4.12 + * This program is distributed in the hope that it will be useful,
4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.15 + * GNU General Public License for more details.
4.16 + *
4.17 + * You should have received a copy of the GNU General Public License
4.18 + * along with this program; if not, write to the Free Software
4.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4.20 + */
4.21 +
4.22 +#include <map>
4.23 +#include "ns3/object.h"
4.24 +#include "ns3/log.h"
4.25 +#include "ns3/assert.h"
4.26 +#include "ns3/abort.h"
4.27 +#include "ns3/simulator.h"
4.28 +#include "object-names.h"
4.29 +
4.30 +namespace ns3 {
4.31 +
4.32 +NS_LOG_COMPONENT_DEFINE ("Names");
4.33 +
4.34 +class NameNode
4.35 +{
4.36 +public:
4.37 + NameNode ();
4.38 + NameNode (const NameNode &nameNode);
4.39 + NameNode (NameNode *parent, std::string name, Ptr<Object> object);
4.40 + NameNode &operator = (const NameNode &rhs);
4.41 +
4.42 + ~NameNode ();
4.43 +
4.44 + NameNode *m_parent;
4.45 + std::string m_name;
4.46 + Ptr<Object> m_object;
4.47 +
4.48 + std::map<std::string, NameNode *> m_nameMap;
4.49 +};
4.50 +
4.51 +NameNode::NameNode ()
4.52 + : m_parent (0), m_name (""), m_object (0)
4.53 +{
4.54 +}
4.55 +
4.56 +NameNode::NameNode (const NameNode &nameNode)
4.57 +{
4.58 + m_parent = nameNode.m_parent;
4.59 + m_name = nameNode.m_name;
4.60 + m_object = nameNode.m_object;
4.61 + m_nameMap = nameNode.m_nameMap;
4.62 +}
4.63 +
4.64 +NameNode &
4.65 +NameNode::operator = (const NameNode &rhs)
4.66 +{
4.67 + m_parent = rhs.m_parent;
4.68 + m_name = rhs.m_name;
4.69 + m_object = rhs.m_object;
4.70 + m_nameMap = rhs.m_nameMap;
4.71 + return *this;
4.72 +}
4.73 +
4.74 +NameNode::NameNode (NameNode *parent, std::string name, Ptr<Object> object)
4.75 + : m_parent (parent), m_name (name), m_object (object)
4.76 +{
4.77 +}
4.78 +
4.79 +NameNode::~NameNode ()
4.80 +{
4.81 +}
4.82 +
4.83 +class NamesPriv
4.84 +{
4.85 +public:
4.86 + NamesPriv ();
4.87 + ~NamesPriv ();
4.88 +
4.89 + bool Add (std::string name, Ptr<Object> obj);
4.90 + bool Add (Ptr<Object> context, std::string name, Ptr<Object> object);
4.91 + bool Add (std::string context, std::string name, Ptr<Object> object);
4.92 + std::string FindShortName (Ptr<Object> object);
4.93 + std::string FindFullName (Ptr<Object> object);
4.94 + Ptr<Object> FindObjectFromFullName (std::string name);
4.95 + Ptr<Object> FindObjectFromShortName (Ptr<Object> context, std::string name);
4.96 +
4.97 + static NamesPriv *Get (void);
4.98 +
4.99 +private:
4.100 + static NamesPriv **DoGet (void);
4.101 + static void Delete (void);
4.102 +
4.103 + NameNode *IsNamed (Ptr<Object>);
4.104 + bool IsDuplicateName (NameNode *node, std::string name);
4.105 +
4.106 + NameNode m_root;
4.107 + std::map<Ptr<Object>, NameNode *> m_objectMap;
4.108 +};
4.109 +
4.110 +NamesPriv *
4.111 +NamesPriv::Get (void)
4.112 +{
4.113 + return *(DoGet ());
4.114 +}
4.115 +
4.116 +NamesPriv **
4.117 +NamesPriv::DoGet (void)
4.118 +{
4.119 + static NamesPriv *ptr = 0;
4.120 +
4.121 + if (ptr == 0)
4.122 + {
4.123 + ptr = new NamesPriv;
4.124 + Simulator::ScheduleDestroy (&NamesPriv::Delete);
4.125 + }
4.126 +
4.127 + return &ptr;
4.128 +}
4.129 +
4.130 +void
4.131 +NamesPriv::Delete (void)
4.132 +{
4.133 + NS_LOG_FUNCTION_NOARGS ();
4.134 +
4.135 + NamesPriv **ptr = DoGet ();
4.136 + delete *ptr;
4.137 + *ptr = 0;
4.138 +}
4.139 +
4.140 +NamesPriv::NamesPriv ()
4.141 +{
4.142 + NS_LOG_FUNCTION_NOARGS ();
4.143 +
4.144 + m_root.m_parent = 0;
4.145 + m_root.m_name = "Names";
4.146 + m_root.m_object = 0;
4.147 +}
4.148 +
4.149 +NamesPriv::~NamesPriv ()
4.150 +{
4.151 + NS_LOG_FUNCTION_NOARGS ();
4.152 +
4.153 + //
4.154 + // Every name is associated with an object in the object map, so freeing the
4.155 + // NameNodes in this map will free all of the memory allocated for the NameNodes
4.156 + //
4.157 + for (std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.begin (); i != m_objectMap.end (); ++i)
4.158 + {
4.159 + delete i->second;
4.160 + i->second = 0;
4.161 + }
4.162 +}
4.163 +
4.164 +bool
4.165 +NamesPriv::Add (std::string name, Ptr<Object> object)
4.166 +{
4.167 + return Add (Ptr<Object> (0, false), name, object);
4.168 +}
4.169 +
4.170 +bool
4.171 +NamesPriv::Add (Ptr<Object> context, std::string name, Ptr<Object> object)
4.172 +{
4.173 + NS_LOG_FUNCTION (context << name << object);
4.174 +
4.175 + if (IsNamed (object))
4.176 + {
4.177 + NS_LOG_LOGIC ("Object is already named");
4.178 + return false;
4.179 + }
4.180 +
4.181 + NameNode *node = 0;
4.182 + if (context)
4.183 + {
4.184 + node = IsNamed (context);
4.185 + NS_ASSERT_MSG (node, "NamesPriv::Name(): context must point to a previously named node");
4.186 + }
4.187 + else
4.188 + {
4.189 + node = &m_root;
4.190 + }
4.191 +
4.192 + if (IsDuplicateName (node, name))
4.193 + {
4.194 + NS_LOG_LOGIC ("Name is already taken");
4.195 + return false;
4.196 + }
4.197 +
4.198 + NameNode *newNode = new NameNode(node, name, object);
4.199 + node->m_nameMap[name] = newNode;
4.200 + m_objectMap[object] = newNode;
4.201 +
4.202 + return true;
4.203 +}
4.204 +
4.205 +bool
4.206 +NamesPriv::Add (std::string context, std::string name, Ptr<Object> object)
4.207 +{
4.208 + if (context == "/Names")
4.209 + {
4.210 + return Add (name, object);
4.211 + }
4.212 + return Add (FindObjectFromFullName (context), name, object);
4.213 +}
4.214 +
4.215 +std::string
4.216 +NamesPriv::FindShortName (Ptr<Object> object)
4.217 +{
4.218 + NS_LOG_FUNCTION (object);
4.219 +
4.220 + std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
4.221 + if (i == m_objectMap.end ())
4.222 + {
4.223 + NS_LOG_LOGIC ("Object does not exist in object map");
4.224 + return "";
4.225 + }
4.226 + else
4.227 + {
4.228 + NS_LOG_LOGIC ("Object exists in object map");
4.229 + return i->second->m_name;
4.230 + }
4.231 +}
4.232 +
4.233 +std::string
4.234 +NamesPriv::FindFullName (Ptr<Object> object)
4.235 +{
4.236 + NS_LOG_FUNCTION (object);
4.237 +
4.238 + std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
4.239 + if (i == m_objectMap.end ())
4.240 + {
4.241 + NS_LOG_LOGIC ("Object does not exist in object map");
4.242 + return "";
4.243 + }
4.244 +
4.245 + NameNode *p = i->second;
4.246 + NS_ASSERT_MSG (p, "NamesPriv::FindFullName(): Internal error: Invalid NameNode pointer from map");
4.247 +
4.248 + std::string fullname;
4.249 +
4.250 + do
4.251 + {
4.252 + fullname = "/" + p->m_name + fullname;
4.253 + NS_LOG_LOGIC ("fullname is " << fullname);
4.254 + }
4.255 + while ((p = p->m_parent) != 0);
4.256 +
4.257 + return fullname;
4.258 +}
4.259 +
4.260 +
4.261 +Ptr<Object>
4.262 +NamesPriv::FindObjectFromFullName (std::string name)
4.263 +{
4.264 + std::string namespaceName = "/Names/";
4.265 + std::string::size_type offset = name.find (namespaceName);
4.266 + if (offset == std::string::npos)
4.267 + {
4.268 + NS_LOG_LOGIC (name << " is not in the " << namespaceName << " name space");
4.269 + return 0;
4.270 + }
4.271 +
4.272 + std::string remaining = name.substr (namespaceName.size ());
4.273 + NameNode *node = &m_root;
4.274 +
4.275 + //
4.276 + // remaining is now composed entirely of path segments in the /Names name space.
4.277 + // and we have eaten the leading slash. e.g., remaining = "ClientNode/eth0"
4.278 + // The start of the search is at the root of the name space.
4.279 + //
4.280 + for (;;)
4.281 + {
4.282 + NS_LOG_LOGIC ("Looking for the object of name " << remaining);
4.283 + offset = remaining.find ("/");
4.284 + if (offset == std::string::npos)
4.285 + {
4.286 + //
4.287 + // There are no remaining slashes so this is the last segment of the
4.288 + // specified name. We're done when we find it
4.289 + //
4.290 + std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (remaining);
4.291 + if (i == node->m_nameMap.end ())
4.292 + {
4.293 + NS_LOG_LOGIC ("Name does not exist in name map");
4.294 + return 0;
4.295 + }
4.296 + else
4.297 + {
4.298 + NS_LOG_LOGIC ("Name parsed, found object");
4.299 + return i->second->m_object;
4.300 + }
4.301 + }
4.302 + else
4.303 + {
4.304 + //
4.305 + // There are more slashes so this is an intermediate segment of the
4.306 + // specified name. We need to "recurse" when we find this segment.
4.307 + //
4.308 + offset = remaining.find ("/");
4.309 + std::string segment = remaining.substr(0, offset);
4.310 +
4.311 + std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (segment);
4.312 + if (i == node->m_nameMap.end ())
4.313 + {
4.314 + NS_LOG_LOGIC ("Name does not exist in name map");
4.315 + return 0;
4.316 + }
4.317 + else
4.318 + {
4.319 + node = i->second;
4.320 + remaining = remaining.substr (offset + 1);
4.321 + NS_LOG_LOGIC ("Intermediate segment parsed");
4.322 + continue;
4.323 + }
4.324 + }
4.325 + }
4.326 +
4.327 + NS_ASSERT_MSG (node, "NamesPriv::FindObjectFromFullName(): Internal error: this can't happen");
4.328 + return 0;
4.329 +}
4.330 +
4.331 +Ptr<Object>
4.332 +NamesPriv::FindObjectFromShortName (Ptr<Object> context, std::string name)
4.333 +{
4.334 + NS_LOG_FUNCTION (context << name);
4.335 +
4.336 + NameNode *node = 0;
4.337 +
4.338 + if (context == 0)
4.339 + {
4.340 + NS_LOG_LOGIC ("Zero context implies root NameNode");
4.341 + node = &m_root;
4.342 + }
4.343 + else
4.344 + {
4.345 + node = IsNamed (context);
4.346 + if (node == 0)
4.347 + {
4.348 + NS_LOG_LOGIC ("Context does not point to a previously named node");
4.349 + return 0;
4.350 + }
4.351 + }
4.352 +
4.353 + std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (name);
4.354 + if (i == node->m_nameMap.end ())
4.355 + {
4.356 + NS_LOG_LOGIC ("Name does not exist in name map");
4.357 + return 0;
4.358 + }
4.359 + else
4.360 + {
4.361 + NS_LOG_LOGIC ("Name exists in name map");
4.362 + return i->second->m_object;
4.363 + }
4.364 +}
4.365 +
4.366 +NameNode *
4.367 +NamesPriv::IsNamed (Ptr<Object> object)
4.368 +{
4.369 + NS_LOG_FUNCTION (object);
4.370 +
4.371 + std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
4.372 + if (i == m_objectMap.end ())
4.373 + {
4.374 + NS_LOG_LOGIC ("Object does not exist in object map, returning NameNode 0");
4.375 + return 0;
4.376 + }
4.377 + else
4.378 + {
4.379 + NS_LOG_LOGIC ("Object exists in object map, returning NameNode " << &i->second);
4.380 + return i->second;
4.381 + }
4.382 +}
4.383 +
4.384 +bool
4.385 +NamesPriv::IsDuplicateName (NameNode *node, std::string name)
4.386 +{
4.387 + NS_LOG_FUNCTION (node << name);
4.388 +
4.389 + std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (name);
4.390 + if (i == node->m_nameMap.end ())
4.391 + {
4.392 + NS_LOG_LOGIC ("Name does not exist in name map");
4.393 + return false;
4.394 + }
4.395 + else
4.396 + {
4.397 + NS_LOG_LOGIC ("Name exists in name map");
4.398 + return true;
4.399 + }
4.400 +}
4.401 +
4.402 +bool
4.403 +Names::Add (std::string name, Ptr<Object> object)
4.404 +{
4.405 + return NamesPriv::Get ()->Add (name, object);
4.406 +}
4.407 +
4.408 +bool
4.409 +Names::Add (Ptr<Object> context, std::string name, Ptr<Object> object)
4.410 +{
4.411 + return NamesPriv::Get ()->Add (context, name, object);
4.412 +}
4.413 +
4.414 +bool
4.415 +Names::Add (std::string context, std::string name, Ptr<Object> object)
4.416 +{
4.417 + return NamesPriv::Get ()->Add (context, name, object);
4.418 +}
4.419 +
4.420 +std::string
4.421 +Names::FindShortName (Ptr<Object> object)
4.422 +{
4.423 + return NamesPriv::Get ()->FindShortName (object);
4.424 +}
4.425 +
4.426 +std::string
4.427 +Names::FindFullName (Ptr<Object> object)
4.428 +{
4.429 + return NamesPriv::Get ()->FindFullName (object);
4.430 +}
4.431 +
4.432 +Ptr<Object>
4.433 +Names::FindObjectFromFullNameInternal (std::string name)
4.434 +{
4.435 + return NamesPriv::Get ()->FindObjectFromFullName (name);
4.436 +}
4.437 +
4.438 +Ptr<Object>
4.439 +Names::FindObjectFromShortNameInternal (Ptr<Object> context, std::string name)
4.440 +{
4.441 + return NamesPriv::Get ()->FindObjectFromShortName (context, name);
4.442 +}
4.443 +
4.444 +} //namespace ns3
4.445 +
4.446 +#ifdef RUN_SELF_TESTS
4.447 +
4.448 +#include "test.h"
4.449 +#include "object-factory.h"
4.450 +
4.451 +namespace ns3 {
4.452 +
4.453 +class TestObject : public Object
4.454 +{
4.455 +public:
4.456 + static TypeId GetTypeId (void)
4.457 + {
4.458 + static TypeId tid = TypeId ("TestObject")
4.459 + .SetParent (Object::GetTypeId ())
4.460 + .HideFromDocumentation ()
4.461 + .AddConstructor<TestObject> ();
4.462 + return tid;
4.463 + }
4.464 + TestObject () {}
4.465 + virtual void Dispose (void) {}
4.466 +};
4.467 +
4.468 +class NamesTest : public Test
4.469 +{
4.470 +public:
4.471 + NamesTest ();
4.472 + virtual bool RunTests (void);
4.473 +};
4.474 +
4.475 +NamesTest::NamesTest ()
4.476 + : Test ("Names")
4.477 +{
4.478 +}
4.479 +
4.480 +bool
4.481 +NamesTest::RunTests (void)
4.482 +{
4.483 + bool result = true;
4.484 +
4.485 + //
4.486 + // Name a couple of objects at the root level
4.487 + //
4.488 + Ptr<TestObject> client = CreateObject<TestObject> ();
4.489 + result = Names::Add ("Client", client);
4.490 + NS_TEST_ASSERT_EQUAL (result, true);
4.491 +
4.492 + Ptr<TestObject> server = CreateObject<TestObject> ();
4.493 + result = Names::Add ("Server", server);
4.494 + NS_TEST_ASSERT_EQUAL (result, true);
4.495 +
4.496 + //
4.497 + // We shouldn't be able to add another name to a previously named object
4.498 + //
4.499 + result = Names::Add ("Not Client", client);
4.500 + NS_TEST_ASSERT_EQUAL (result, false);
4.501 +
4.502 + //
4.503 + // We shouldn't be able to duplicate a name at the root level.
4.504 + //
4.505 + Ptr<TestObject> secondClient = CreateObject<TestObject> ();
4.506 + result = Names::Add ("Client", secondClient);
4.507 + NS_TEST_ASSERT_EQUAL (result, false);
4.508 +
4.509 + //
4.510 + // We should be able to add a new name in the first object's context
4.511 + //
4.512 + Ptr<TestObject> clientEth0 = CreateObject<TestObject> ();
4.513 + result = Names::Add (client, "eth0", clientEth0);
4.514 + NS_TEST_ASSERT_EQUAL (result, true);
4.515 +
4.516 + //
4.517 + // We shouldn't be able to duplicate a name in that context.
4.518 + //
4.519 + Ptr<TestObject> secondClientEth0 = CreateObject<TestObject> ();
4.520 + result = Names::Add (client, "eth0", secondClientEth0);
4.521 + NS_TEST_ASSERT_EQUAL (result, false);
4.522 +
4.523 + //
4.524 + // We should be able to add the same name in the second object's context
4.525 + //
4.526 + Ptr<TestObject> serverEth0 = CreateObject<TestObject> ();
4.527 + result = Names::Add (server, "eth0", serverEth0);
4.528 + NS_TEST_ASSERT_EQUAL (result, true);
4.529 +
4.530 + //
4.531 + // We should be able to find the short names for the objects we created
4.532 + //
4.533 + std::string found;
4.534 +
4.535 + found = Names::FindShortName (client);
4.536 + NS_TEST_ASSERT_EQUAL (found, "Client");
4.537 +
4.538 + found = Names::FindShortName (server);
4.539 + NS_TEST_ASSERT_EQUAL (found, "Server");
4.540 +
4.541 + found = Names::FindShortName (clientEth0);
4.542 + NS_TEST_ASSERT_EQUAL (found, "eth0");
4.543 +
4.544 + found = Names::FindShortName (serverEth0);
4.545 + NS_TEST_ASSERT_EQUAL (found, "eth0");
4.546 +
4.547 + //
4.548 + // We should be able to find the full names for the objects we created
4.549 + //
4.550 + found = Names::FindFullName (client);
4.551 + NS_TEST_ASSERT_EQUAL (found, "/Names/Client");
4.552 +
4.553 + found = Names::FindFullName (server);
4.554 + NS_TEST_ASSERT_EQUAL (found, "/Names/Server");
4.555 +
4.556 + found = Names::FindFullName (clientEth0);
4.557 + NS_TEST_ASSERT_EQUAL (found, "/Names/Client/eth0");
4.558 +
4.559 + found = Names::FindFullName (serverEth0);
4.560 + NS_TEST_ASSERT_EQUAL (found, "/Names/Server/eth0");
4.561 +
4.562 + //
4.563 + // We should be able to find the objects from the short names
4.564 + //
4.565 + Ptr<TestObject> foundObject;
4.566 +
4.567 + foundObject = Names::FindObjectFromShortName<TestObject> (0, "Client");
4.568 + NS_TEST_ASSERT_EQUAL (foundObject, client);
4.569 +
4.570 + foundObject = Names::FindObjectFromShortName<TestObject> (0, "Server");
4.571 + NS_TEST_ASSERT_EQUAL (foundObject, server);
4.572 +
4.573 + foundObject = Names::FindObjectFromShortName<TestObject> (client, "eth0");
4.574 + NS_TEST_ASSERT_EQUAL (foundObject, clientEth0);
4.575 +
4.576 + foundObject = Names::FindObjectFromShortName<TestObject> (server, "eth0");
4.577 + NS_TEST_ASSERT_EQUAL (foundObject, serverEth0);
4.578 +
4.579 + //
4.580 + // We should be able to find the objects from their full names
4.581 + //
4.582 + foundObject = Names::Find<TestObject> ("/Names/Client");
4.583 + NS_TEST_ASSERT_EQUAL (foundObject, client);
4.584 +
4.585 + foundObject = Names::Find<TestObject> ("/Names/Server");
4.586 + NS_TEST_ASSERT_EQUAL (foundObject, server);
4.587 +
4.588 + foundObject = Names::Find<TestObject> ("/Names/Client/eth0");
4.589 + NS_TEST_ASSERT_EQUAL (foundObject, clientEth0);
4.590 +
4.591 + foundObject = Names::Find<TestObject> ("/Names/Server/eth0");
4.592 + NS_TEST_ASSERT_EQUAL (foundObject, serverEth0);
4.593 +
4.594 + //
4.595 + // We also have some syntactical sugary methods, so make sure they do what
4.596 + // they should as well.
4.597 + //
4.598 + Ptr<TestObject> bridge = CreateObject<TestObject> ();
4.599 + result = Names::Add ("/Names", "Bridge", client);
4.600 + NS_TEST_ASSERT_EQUAL (result, true);
4.601 +
4.602 + Ptr<TestObject> bridgeEth0 = CreateObject<TestObject> ();
4.603 + result = Names::Add ("/Names/Bridge", "eth0", bridgeEth0);
4.604 + NS_TEST_ASSERT_EQUAL (result, true);
4.605 +
4.606 + foundObject = Names::Find<TestObject> ("/Names/Bridge");
4.607 + NS_TEST_ASSERT_EQUAL (foundObject, bridge);
4.608 +
4.609 + foundObject = Names::Find<TestObject> ("/Names/Bridge/eth0");
4.610 + NS_TEST_ASSERT_EQUAL (foundObject, bridgeEth0);
4.611 +
4.612 + //
4.613 + // Run the simulator and destroy it to get the Destroy method called on the
4.614 + // private implementation object. We depend on seeing a valgrind-clean run of
4.615 + // the unit tests to really determine if the clean up was really successful.
4.616 + //
4.617 + Simulator::Run ();
4.618 + Simulator::Destroy ();
4.619 +
4.620 + return true;
4.621 +}
4.622 +
4.623 +static NamesTest g_namesTests;
4.624 +
4.625 +} // namespace ns3
4.626 +
4.627 +#endif /* RUN_SELF_TESTS */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/src/core/object-names.h Tue Jan 20 15:47:14 2009 -0800
5.3 @@ -0,0 +1,245 @@
5.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
5.5 +/*
5.6 + * Copyright (c) 2009 University of Washington
5.7 + *
5.8 + * This program is free software; you can redistribute it and/or modify
5.9 + * it under the terms of the GNU General Public License version 2 as
5.10 + * published by the Free Software Foundation;
5.11 + *
5.12 + * This program is distributed in the hope that it will be useful,
5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.15 + * GNU General Public License for more details.
5.16 + *
5.17 + * You should have received a copy of the GNU General Public License
5.18 + * along with this program; if not, write to the Free Software
5.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5.20 + */
5.21 +
5.22 +#ifndef OBJECT_NAMES_H
5.23 +#define OBJECT_NAMES_H
5.24 +
5.25 +#include "ns3/ptr.h"
5.26 +#include "ns3/object.h"
5.27 +
5.28 +namespace ns3 {
5.29 +
5.30 +/**
5.31 + * \brief A directory of name and Ptr<Object> associations that allows us to
5.32 + * give any ns3 Object a name.
5.33 + */
5.34 +class Names
5.35 +{
5.36 +public:
5.37 +
5.38 + /**
5.39 + * Add the association between the string "name" and the Ptr<Object> obj
5.40 + * at the root of the "/Names" name space. This can be seen as equivalent
5.41 + * to adding a Pointer Attribute called "name" to the to the root name
5.42 + * space object and then assigning the value obj to that attribute. The
5.43 + * config facility will see it that way.
5.44 + *
5.45 + * \param name The name of the object you want to associate.
5.46 + * \param obj A smart pointer to the object itself.
5.47 + */
5.48 + static bool Add (std::string name, Ptr<Object> obj);
5.49 +
5.50 + /**
5.51 + * Add the association between the string "name" and the Ptr<Object> obj
5.52 + * in the object context given by the Ptr<Object> context. This can be
5.53 + * seen as equivalent to adding a Pointer Attribute called "name" to the
5.54 + * object given by "context" and then assigning the value obj to that
5.55 + * attribute. The config facility will see it that way.
5.56 + *
5.57 + * \param context A spart pointer to an object under which you want this
5.58 + * name to be defined.
5.59 + * \param name The name of the object you want to associate.
5.60 + * \param obj A smart pointer to the object itself.
5.61 + */
5.62 + static bool Add (Ptr<Object> context, std::string name, Ptr<Object> object);
5.63 +
5.64 + /**
5.65 + * Syntactic sugar around the Object context Name method. Allows you to
5.66 + * specify the context with a string instead of the pointer. If the first
5.67 + * parameter (context) is "/Names" this turns into a call into Name at the
5.68 + * root of the name space. Otherwise it does a FindObjectFromFullNameInternal
5.69 + * on the context and adds the name to a subspace.
5.70 + *
5.71 + * \param context A fully qualified name describing a previously named object.
5.72 + * under which you want this name to be defined.
5.73 + * \param name The name of the object you want to associate.
5.74 + * \param obj A smart pointer to the object itself.
5.75 + */
5.76 + static bool Add (std::string context, std::string name, Ptr<Object> object);
5.77 +
5.78 + /**
5.79 + * Given a pointer to an object, look to see if that object has a name
5.80 + * associated with it and return the shortname for the object.
5.81 + *
5.82 + * The fullname of an object is a fully qualified namespace name, for example
5.83 + * if you have a device that you have previously named "eth0" under a node
5.84 + * you have named "client", the fullname of the device will then be
5.85 + * "/Names/client/eth0".
5.86 + *
5.87 + * The shortname of an object is the name of the object in its parent name
5.88 + * space. Using the example above, asking for the shortname of the device
5.89 + * will result in "eth0" being returned.
5.90 + *
5.91 + * \param object A spart pointer to an object for which you want to find
5.92 + * its shortname.
5.93 + */
5.94 + static std::string FindShortName (Ptr<Object> object);
5.95 +
5.96 + /**
5.97 + * Given a pointer to an object, look to see if that object has a name
5.98 + * associated with it and return the fully qualified namespace name
5.99 + * for the object.
5.100 + *
5.101 + * The fullname of an object is a fully qualified namespace name, for example
5.102 + * if you have a device that you have previously named "eth0" under a node
5.103 + * you have named "client", the fullname of the device will then be
5.104 + * "/Names/client/eth0".
5.105 + *
5.106 + * The shortname of an object is the name of the object in its parent name
5.107 + * space. Using the example above, asking for the shortname of the device
5.108 + * will result in "eth0" being returned.
5.109 + *
5.110 + * \param object A spart pointer to an object for which you want to find
5.111 + * its fullname.
5.112 + */
5.113 + static std::string FindFullName (Ptr<Object> object);
5.114 +
5.115 + /**
5.116 + * Given a fullname string, look to see if there's an object in the system
5.117 + * with a that associated with it. If there is, do a QueryObject on the
5.118 + * resulting object to convert it to the requested typename.
5.119 + *
5.120 + * The fullname of an object is a fully qualified namespace name, for example
5.121 + * if you have a device that you have previously named "eth0" under a node
5.122 + * you have named "client", the fullname of the device will then be
5.123 + * "/Names/client/eth0".
5.124 + *
5.125 + * \param name A string containing a fully qualified name space name
5.126 + * used to locate the object.
5.127 + */
5.128 + template <typename T>
5.129 + static Ptr<T> FindObjectFromFullName (std::string name);
5.130 +
5.131 + /**
5.132 + * Given a fullname string, look to see if there's an object in the system
5.133 + * with a that associated with it. If there is, do a QueryObject on the
5.134 + * resulting object to convert it to the requested typename.
5.135 + *
5.136 + * The fullname of an object is a fully qualified namespace name, for example
5.137 + * if you have a device that you have previously named "eth0" under a node
5.138 + * you have named "client", the fullname of the device will then be
5.139 + * "/Names/client/eth0".
5.140 + *
5.141 + * \param name A string containing a fully qualified name space name
5.142 + * used to locate the object.
5.143 + *
5.144 + * @comment This method is identical to FindObjectFromFullName, but has a
5.145 + * short signature since it is a common use and we want it to be easy to
5.146 + * type.
5.147 + */
5.148 + template <typename T>
5.149 + static Ptr<T> Find (std::string name);
5.150 +
5.151 + /**
5.152 + * Given an object context and a shortname string, look through the names
5.153 + * associated with the namespace defined by the context object to see if
5.154 + * there's an object there with the given shortname.
5.155 + *
5.156 + * The fullname of an object is a fully qualified namespace name, for example
5.157 + * if you have a device that you have previously named "eth0" under a node
5.158 + * you have named "client", the fullname of the device will then be
5.159 + * "/Names/client/eth0".
5.160 + *
5.161 + * The shortname of an object is the name of the object in its parent name
5.162 + * space. Using the example above, asking for the shortname of the device
5.163 + * will result in "eth0" being returned.
5.164 + *
5.165 + * The context object provides a namespace context, in the case of the example
5.166 + * it would be the "client" object under which we look for the short name.
5.167 + * In the example above, the context pointer would be the Ptr<Object> to the
5.168 + * client node, and the name would be the shortname "eth0"
5.169 + *
5.170 + * \param context A spart pointer to an object under which you want to look
5.171 + * for the provided name.
5.172 + * \param name A string containing a shortname to look for.
5.173 + */
5.174 + template <typename T>
5.175 + static Ptr<T> FindObjectFromShortName (Ptr<Object> context, std::string name);
5.176 +
5.177 +private:
5.178 +
5.179 + /**
5.180 + * \internal
5.181 + *
5.182 + * \brief Non-templated internal version of FindObjectFromLongName
5.183 + *
5.184 + * \param name A string containing a longname to look for.
5.185 + */
5.186 + static Ptr<Object> FindObjectFromFullNameInternal (std::string name);
5.187 +
5.188 + /**
5.189 + * \internal
5.190 + *
5.191 + * \brief Non-templated internal version of FindObjectFromShortName
5.192 + *
5.193 + * \param context A spart pointer to an object under which you want to look
5.194 + * for the provided name.
5.195 + * \param name A string containing a shortname to look for.
5.196 + */
5.197 + static Ptr<Object> FindObjectFromShortNameInternal (Ptr<Object> context, std::string name);
5.198 +};
5.199 +
5.200 +/**
5.201 + * \brief Template definition of corresponding template declaration found in class Names.
5.202 + */
5.203 +template <typename T>
5.204 +Ptr<T>
5.205 +Names::Find (std::string name)
5.206 +{
5.207 + return FindObjectFromFullName<T> (name);
5.208 +}
5.209 +
5.210 +/**
5.211 + * \brief Template definition of corresponding template declaration found in class Names.
5.212 + */
5.213 +template <typename T>
5.214 +Ptr<T>
5.215 +Names::FindObjectFromFullName (std::string name)
5.216 +{
5.217 + Ptr<Object> obj = FindObjectFromFullNameInternal (name);
5.218 + if (obj)
5.219 + {
5.220 + return obj->GetObject<T> ();
5.221 + }
5.222 + else
5.223 + {
5.224 + return 0;
5.225 + }
5.226 +}
5.227 +
5.228 +/**
5.229 + * \brief Template definition of corresponding template declaration found in class Names.
5.230 + */
5.231 +template <typename T>
5.232 +Ptr<T>
5.233 +Names::FindObjectFromShortName (Ptr<Object> context, std::string name)
5.234 +{
5.235 + Ptr<Object> obj = FindObjectFromShortNameInternal (context, name);
5.236 + if (obj)
5.237 + {
5.238 + return obj->GetObject<T> ();
5.239 + }
5.240 + else
5.241 + {
5.242 + return 0;
5.243 + }
5.244 +}
5.245 +
5.246 +}//namespace ns3
5.247 +
5.248 +#endif /* OBJECT_NAMES_H */
6.1 --- a/src/core/wscript Sun Jan 18 22:47:25 2009 +0000
6.2 +++ b/src/core/wscript Tue Jan 20 15:47:14 2009 -0800
6.3 @@ -53,6 +53,7 @@
6.4 'trace-source-accessor.cc',
6.5 'config.cc',
6.6 'callback.cc',
6.7 + 'object-names.cc',
6.8 ]
6.9 core.uselib = 'RT'
6.10
6.11 @@ -98,6 +99,7 @@
6.12 'object-vector.h',
6.13 'deprecated.h',
6.14 'abort.h',
6.15 + 'object-names.h',
6.16 ]
6.17
6.18 if sys.platform == 'win32':