A Discrete-Event Network Simulator
API
object-base.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 INRIA
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  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "object-base.h"
21 #include "log.h"
22 #include "trace-source-accessor.h"
24 #include "string.h"
25 #include "ns3/core-config.h"
26 
27 #include <cstdlib> // getenv
28 #include <cstring> // strlen
29 #include <unordered_map>
30 
37 namespace ns3 {
38 
39 NS_LOG_COMPONENT_DEFINE ("ObjectBase");
40 
41 NS_OBJECT_ENSURE_REGISTERED (ObjectBase);
42 
44 namespace {
45 
52 std::pair<bool, std::string>
53 EnvDictionary (std::string key)
54 {
55  static std::unordered_map<std::string, std::string> dict;
56 
57  if (dict.size () == 0)
58  {
59  const char *envVar = getenv ("NS_ATTRIBUTE_DEFAULT");
60  if (envVar != 0 && std::strlen (envVar) > 0)
61  {
62  std::string env = envVar;
63  std::string::size_type cur = 0;
64  std::string::size_type next = 0;
65  while (next != std::string::npos)
66  {
67  next = env.find (";", cur);
68  std::string tmp = std::string (env, cur, next - cur);
69  std::string::size_type equal = tmp.find ("=");
70  if (equal != std::string::npos)
71  {
72  std::string name = tmp.substr (0, equal);
73  std::string envval = tmp.substr (equal + 1, tmp.size () - equal - 1);
74  dict.insert ({name, envval});
75  }
76  cur = next + 1;
77  }
78  }
79  else
80  {
81  // insert an empty key, so we don't do this again
82  dict.insert ({"", ""});
83  }
84  }
85 
86  std::string value;
87  bool found {false};
88 
89  auto loc = dict.find (key);
90  if (loc != dict.end ())
91  {
92  value = loc->second;
93  found = true;
94  }
95  return {found, value};
96 }
97 
98 } // unnamed namespace
99 
100 
109 static TypeId
111 {
113  TypeId tid = TypeId ("ns3::ObjectBase");
114  tid.SetParent (tid);
115  tid.SetGroupName ("Core");
116  return tid;
117 }
118 
119 TypeId
121 {
123  static TypeId tid = GetObjectIid ();
124  return tid;
125 }
126 
128 {
129  NS_LOG_FUNCTION (this);
130 }
131 
132 void
134 {
135  NS_LOG_FUNCTION (this);
136 }
137 
144 #ifdef NS3_LOG_ENABLE
145 #define LOG_WHERE_VALUE(where, value) \
146  do { \
147  std::string valStr {"nothing"}; \
148  if (value) \
149  { \
150  valStr = "\"" + value->SerializeToString (info.checker) + "\""; \
151  } \
152  NS_LOG_DEBUG (where << " gave " << valStr); \
153  } while (false)
154 #else
155 #define LOG_WHERE_VALUE(where, value)
156 #endif
157 
158 void
160 {
161  // loop over the inheritance tree back to the Object base class.
162  NS_LOG_FUNCTION (this << &attributes);
163  TypeId tid = GetInstanceTypeId ();
164  do // Do this tid and all parents
165  {
166  // loop over all attributes in object type
167  NS_LOG_DEBUG ("construct tid=" << tid.GetName () <<
168  ", params=" << tid.GetAttributeN ());
169  for (uint32_t i = 0; i < tid.GetAttributeN (); i++)
170  {
171  struct TypeId::AttributeInformation info = tid.GetAttribute (i);
172  NS_LOG_DEBUG ("try to construct \"" << tid.GetName () << "::" <<
173  info.name << "\"");
174 
175  Ptr<const AttributeValue> value = attributes.Find (info.checker);
176  std::string where = "argument";
177 
178  LOG_WHERE_VALUE (where, value);
179  // See if this attribute should not be set here in the
180  // constructor.
181  if (!(info.flags & TypeId::ATTR_CONSTRUCT))
182  {
183  // Handle this attribute if it should not be
184  // set here.
185  if (value == 0)
186  {
187  // Skip this attribute if it's not in the
188  // AttributeConstructionList.
189  NS_LOG_DEBUG ("skipping, not settable at construction");
190  continue;
191  }
192  else
193  {
194  // This is an error because this attribute is not
195  // settable in its constructor but is present in
196  // the AttributeConstructionList.
197  NS_FATAL_ERROR ("Attribute name=" << info.name << " tid=" << tid.GetName () << ": initial value cannot be set using attributes");
198  }
199  }
200 
201  if (!value)
202  {
203  auto [found, val] = EnvDictionary (tid.GetAttributeFullName (i));
204  if (found)
205  {
206  value = Create<StringValue> (val);
207  where = "env var";
208  LOG_WHERE_VALUE (where, value);
209  }
210  }
211 
212  bool initial = false;
213  if (!value)
214  {
215  // Set from Tid initialValue, which is guaranteed to exist
216  value = info.initialValue;
217  where = "initial value";
218  initial = true;
219  LOG_WHERE_VALUE (where, value);
220  }
221 
222  if (DoSet (info.accessor, info.checker, *value) || initial)
223  {
224  // Setting from initial value may fail, e.g. setting
225  // ObjectVectorValue from ""
226  // That's ok, so we still report success since construction is complete
227  NS_LOG_DEBUG ("construct \"" << tid.GetName () << "::" <<
228  info.name << "\" from " << where);
229  }
230 
231  } // for i attributes
232  tid = tid.GetParent ();
233  }
234  while (tid != ObjectBase::GetTypeId ());
236 
237 }
238 #undef LOG_WHERE_VALUE
239 
240 bool
243  const AttributeValue &value)
244 {
245  NS_LOG_FUNCTION (this << accessor << checker << &value);
246  Ptr<AttributeValue> v = checker->CreateValidValue (value);
247  if (v == 0)
248  {
249  return false;
250  }
251  bool ok = accessor->Set (this, *v);
252  return ok;
253 }
254 
255 void
256 ObjectBase::SetAttribute (std::string name, const AttributeValue &value)
257 {
258  NS_LOG_FUNCTION (this << name << &value);
259  struct TypeId::AttributeInformation info;
260  TypeId tid = GetInstanceTypeId ();
261  if (!tid.LookupAttributeByName (name, &info))
262  {
263  NS_FATAL_ERROR ("Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName ());
264  }
265  if (!(info.flags & TypeId::ATTR_SET)
266  || !info.accessor->HasSetter ())
267  {
268  NS_FATAL_ERROR ("Attribute name=" << name << " is not settable for this object: tid=" << tid.GetName ());
269  }
270  if (!DoSet (info.accessor, info.checker, value))
271  {
272  NS_FATAL_ERROR ("Attribute name=" << name << " could not be set for this object: tid=" << tid.GetName ());
273  }
274 }
275 bool
276 ObjectBase::SetAttributeFailSafe (std::string name, const AttributeValue &value)
277 {
278  NS_LOG_FUNCTION (this << name << &value);
279  struct TypeId::AttributeInformation info;
280  TypeId tid = GetInstanceTypeId ();
281  if (!tid.LookupAttributeByName (name, &info))
282  {
283  return false;
284  }
285  if (!(info.flags & TypeId::ATTR_SET)
286  || !info.accessor->HasSetter ())
287  {
288  return false;
289  }
290  return DoSet (info.accessor, info.checker, value);
291 }
292 
293 void
294 ObjectBase::GetAttribute (std::string name, AttributeValue &value) const
295 {
296  NS_LOG_FUNCTION (this << name << &value);
297  struct TypeId::AttributeInformation info;
298  TypeId tid = GetInstanceTypeId ();
299  if (!tid.LookupAttributeByName (name, &info))
300  {
301  NS_FATAL_ERROR ("Attribute name=" << name << " does not exist for this object: tid=" << tid.GetName ());
302  }
303  if (!(info.flags & TypeId::ATTR_GET)
304  || !info.accessor->HasGetter ())
305  {
306  NS_FATAL_ERROR ("Attribute name=" << name << " is not gettable for this object: tid=" << tid.GetName ());
307  }
308  bool ok = info.accessor->Get (this, value);
309  if (ok)
310  {
311  return;
312  }
313  StringValue *str = dynamic_cast<StringValue *> (&value);
314  if (str == 0)
315  {
316  NS_FATAL_ERROR ("Attribute name=" << name << " tid=" << tid.GetName () << ": input value is not a string");
317  }
318  Ptr<AttributeValue> v = info.checker->Create ();
319  ok = info.accessor->Get (this, *PeekPointer (v));
320  if (!ok)
321  {
322  NS_FATAL_ERROR ("Attribute name=" << name << " tid=" << tid.GetName () << ": could not get value");
323  }
324  str->Set (v->SerializeToString (info.checker));
325 }
326 
327 
328 bool
329 ObjectBase::GetAttributeFailSafe (std::string name, AttributeValue &value) const
330 {
331  NS_LOG_FUNCTION (this << name << &value);
332  struct TypeId::AttributeInformation info;
333  TypeId tid = GetInstanceTypeId ();
334  if (!tid.LookupAttributeByName (name, &info))
335  {
336  return false;
337  }
338  if (!(info.flags & TypeId::ATTR_GET)
339  || !info.accessor->HasGetter ())
340  {
341  return false;
342  }
343  bool ok = info.accessor->Get (this, value);
344  if (ok)
345  {
346  return true;
347  }
348  StringValue *str = dynamic_cast<StringValue *> (&value);
349  if (str == 0)
350  {
351  return false;
352  }
353  Ptr<AttributeValue> v = info.checker->Create ();
354  ok = info.accessor->Get (this, *PeekPointer (v));
355  if (!ok)
356  {
357  return false;
358  }
359  str->Set (v->SerializeToString (info.checker));
360  return true;
361 }
362 
363 bool
365 {
366  NS_LOG_FUNCTION (this << name << &cb);
367  TypeId tid = GetInstanceTypeId ();
369  if (accessor == 0)
370  {
371  return false;
372  }
373  bool ok = accessor->ConnectWithoutContext (this, cb);
374  return ok;
375 }
376 bool
377 ObjectBase::TraceConnect (std::string name, std::string context, const CallbackBase &cb)
378 {
379  NS_LOG_FUNCTION (this << name << context << &cb);
380  TypeId tid = GetInstanceTypeId ();
382  if (accessor == 0)
383  {
384  return false;
385  }
386  bool ok = accessor->Connect (this, context, cb);
387  return ok;
388 }
389 bool
391 {
392  NS_LOG_FUNCTION (this << name << &cb);
393  TypeId tid = GetInstanceTypeId ();
395  if (accessor == 0)
396  {
397  return false;
398  }
399  bool ok = accessor->DisconnectWithoutContext (this, cb);
400  return ok;
401 }
402 bool
403 ObjectBase::TraceDisconnect (std::string name, std::string context, const CallbackBase &cb)
404 {
405  NS_LOG_FUNCTION (this << name << context << &cb);
406  TypeId tid = GetInstanceTypeId ();
408  if (accessor == 0)
409  {
410  return false;
411  }
412  bool ok = accessor->Disconnect (this, context, cb);
413  return ok;
414 }
415 
416 
417 
418 } // namespace ns3
ns3::AttributeConstructionList declaration.
List of Attribute name, value and checker triples used to construct Objects.
Ptr< AttributeValue > Find(Ptr< const AttributeChecker > checker) const
Find an Attribute in the list from its AttributeChecker.
Hold a value for an Attribute.
Definition: attribute.h:69
Base class for Callback class.
Definition: callback.h:1196
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
bool TraceDisconnect(std::string name, std::string context, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected with a context.
Definition: object-base.cc:403
static TypeId GetTypeId(void)
Get the type ID.
Definition: object-base.cc:120
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Definition: object-base.cc:390
static TypeId GetObjectIid(void)
Ensure the TypeId for ObjectBase gets fully configured to anchor the inheritance tree properly.
Definition: object-base.cc:110
void ConstructSelf(const AttributeConstructionList &attributes)
Complete construction of ObjectBase; invoked by derived classes.
Definition: object-base.cc:159
virtual ~ObjectBase()
Virtual destructor.
Definition: object-base.cc:127
bool GetAttributeFailSafe(std::string name, AttributeValue &value) const
Get the value of an attribute without raising erros.
Definition: object-base.cc:329
virtual void NotifyConstructionCompleted(void)
Notifier called once the ObjectBase is fully constructed.
Definition: object-base.cc:133
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:276
virtual TypeId GetInstanceTypeId(void) const =0
Get the most derived TypeId for this Object.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:294
bool TraceConnect(std::string name, std::string context, const CallbackBase &cb)
Connect a TraceSource to a Callback with a context.
Definition: object-base.cc:377
bool DoSet(Ptr< const AttributeAccessor > spec, Ptr< const AttributeChecker > checker, const AttributeValue &value)
Attempt to set the value referenced by the accessor spec to a valid value according to the checker,...
Definition: object-base.cc:241
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Hold variables of type string.
Definition: string.h:41
void Set(const std::string &value)
Set the value.
Definition: string.cc:31
a unique identifier for an interface.
Definition: type-id.h:59
std::size_t GetAttributeN(void) const
Get the number of attributes.
Definition: type-id.cc:1076
@ ATTR_GET
The attribute can be read.
Definition: type-id.h:64
@ ATTR_SET
The attribute can be written.
Definition: type-id.h:65
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition: type-id.h:66
std::string GetAttributeFullName(std::size_t i) const
Get the Attribute name by index.
Definition: type-id.cc:1089
struct TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1083
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition: type-id.cc:929
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition: type-id.cc:1177
TypeId GetParent(void) const
Get the parent of this TypeId.
Definition: type-id.cc:943
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Debug message logging.
std::pair< bool, std::string > EnvDictionary(std::string key)
Get key, value pairs from the "NS_ATTRIBUTE_DEFAULT" environment variable.
Definition: object-base.cc:53
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
#define LOG_WHERE_VALUE(where, value)
Log where and what value we find for the attribute.
Definition: object-base.cc:145
ns3::ObjectBase declaration and NS_OBJECT_ENSURE_REGISTERED() madro definition.
ns3::StringValue attribute value declarations.
Attribute implementation.
Definition: type-id.h:78
std::string name
Attribute name.
Definition: type-id.h:80
Ptr< const AttributeAccessor > accessor
Accessor object.
Definition: type-id.h:90
uint32_t flags
AttributeFlags value.
Definition: type-id.h:84
Ptr< const AttributeChecker > checker
Checker object.
Definition: type-id.h:92
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition: type-id.h:88
ns3::TraceSourceAccessor and ns3::MakeTraceSourceAccessor declarations.