merge with ns-3-dev
authorJosh Pelkey <jpelkey@gatech.edu>
Mon Nov 09 13:36:23 2009 -0500 (3 months ago)
changeset 5542c327a4f5fef7
parent 5522 b4da067ee22b
parent 5541 5cb9e32ed4bc
child 5543 f3dd95a9d187
merge with ns-3-dev
AUTHORS
RELEASE_NOTES
src/internet-stack/ipv4-l3-protocol.cc
     1.1 --- a/AUTHORS	Mon Nov 09 13:32:18 2009 -0500
     1.2 +++ b/AUTHORS	Mon Nov 09 13:36:23 2009 -0500
     1.3 @@ -12,23 +12,33 @@
     1.4  Craig Dowell (craigdo@ee.washington.edu)
     1.5  David Gross (gdavid.devel@gmail.com)
     1.6  Tom Henderson (tomhend@u.washington.edu)
     1.7 -Andrey Mazo (mazo@iitp.ru)
     1.8  Sam Jansen (sam.jansen@gmail.com)
     1.9  Liu Jian (liujatp@gmail.com)
    1.10  Joe Kopena (tjkopena@cs.drexel.edu)
    1.11  Aleksey Kovalenko (kovalenko@iitp.ru)
    1.12  Mathieu Lacage (mathieu.lacage@sophia.inria.fr)
    1.13  Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca)
    1.14 +Keith Ma (keith.nwsuaf@gmail.com)
    1.15  Federico Maguolo (maguolof@dei.unipd.it)
    1.16 +Antti Makela (zarhan@cc.hut.fi)
    1.17  Francesco Malandrino (francesco.malandrino@gmail.com)
    1.18 +Fabian Mauchle (f1mauchl@hsr.ch)
    1.19 +Andrey Mazo (mazo@iitp.ru)
    1.20  Faker Moatamri (faker.moatamri@sophia.inria.fr)
    1.21  Duy Nguyen (duy@soe.ucsc.edu)
    1.22 +Tommaso Pecorella (tommaso.pecorella@unifi.it)
    1.23 +Yana Podkosova (yanapdk@rambler.ru)
    1.24  Guangyu Pei (guangyu.pei@boeing.com)
    1.25  George F. Riley (riley@ece.gatech.edu)
    1.26  Providence Salumu Munga (Providence.Salumu@gmail.com, Providence.Salumu_Munga@it-sudparis.eu)
    1.27 +Guillaume Seguin (guillaume.seguin@sophia.inria.fr)
    1.28  Kulin Shah (m.kulin@gmail.com)
    1.29 +Ewgenij Starostin (estar@cs.tu-berlin.de)
    1.30 +Adrian S. W. Tam (adrian.sw.tam@gmail.com)
    1.31 +Wilson Thong (wilsonwk@ee.cityu.edu.hk)
    1.32  Mauro Tortonesi (mauro.tortonesi@unife.it)
    1.33  Sebastien Vincent (vincent@clarinet.u-strasbg.fr)
    1.34  Guillaume Vu-Brugier (gvubrugier@gmail.com)
    1.35 +Tom Wambold (tom5760@gmail.com)
    1.36  Florian Westphal (fw@strlen.de)
    1.37  Josh Pelkey (jpelkey@gatech.edu)
     2.1 --- a/RELEASE_NOTES	Mon Nov 09 13:32:18 2009 -0500
     2.2 +++ b/RELEASE_NOTES	Mon Nov 09 13:36:23 2009 -0500
     2.3 @@ -21,7 +21,6 @@
     2.4    - linux x86_64 gcc 4.4.0, 4.3.2, 4.2.3, 4.2.1, 4.1.3, 3.4.6
     2.5    - MacOS X ppc and x86 (gcc 4.0.x and 4.2.x)
     2.6    - cygwin gcc 3.4.4 (debug only), gcc 4.3.2 (debug and optimized)
     2.7 -  - mingw gcc 3.4.5 (debug only)
     2.8  
     2.9  Not all ns-3 options are available on all platforms; consult the
    2.10  wiki for more information:
    2.11 @@ -78,7 +77,7 @@
    2.12  
    2.13  Known issues
    2.14  ------------
    2.15 -ns-3 build is known to fail on the following platforms:
    2.16 +ns-3.6 build is known to fail on the following platforms:
    2.17    - gcc 3.3 and earlier
    2.18    - optimized builds on gcc 3.4.4 and 3.4.5
    2.19    - optimized builds on linux x86 gcc 4.0.x
     3.1 --- a/src/common/pcap-file-test-suite.cc	Mon Nov 09 13:32:18 2009 -0500
     3.2 +++ b/src/common/pcap-file-test-suite.cc	Mon Nov 09 13:36:23 2009 -0500
     3.3 @@ -107,7 +107,7 @@
     3.4    std::stringstream filename;
     3.5    uint32_t n = rand ();
     3.6    filename << n;
     3.7 -  m_testFilename = "/tmp/" + filename.str () + ".pcap";
     3.8 +  m_testFilename = GetTempDir () + filename.str () + ".pcap";
     3.9  }
    3.10  
    3.11  void
    3.12 @@ -218,7 +218,7 @@
    3.13    std::stringstream filename;
    3.14    uint32_t n = rand ();
    3.15    filename << n;
    3.16 -  m_testFilename = "/tmp/" + filename.str () + ".pcap";
    3.17 +  m_testFilename = GetTempDir () + filename.str () + ".pcap";
    3.18  }
    3.19  
    3.20  void
    3.21 @@ -317,7 +317,7 @@
    3.22    std::stringstream filename;
    3.23    uint32_t n = rand ();
    3.24    filename << n;
    3.25 -  m_testFilename = "/tmp/" + filename.str () + ".pcap";
    3.26 +  m_testFilename = GetTempDir () + filename.str () + ".pcap";
    3.27  }
    3.28  
    3.29  void
    3.30 @@ -416,7 +416,7 @@
    3.31    std::stringstream filename;
    3.32    uint32_t n = rand ();
    3.33    filename << n;
    3.34 -  m_testFilename = "/tmp/" + filename.str () + ".pcap";
    3.35 +  m_testFilename = GetTempDir () + filename.str () + ".pcap";
    3.36  }
    3.37  
    3.38  void
    3.39 @@ -607,7 +607,7 @@
    3.40    std::stringstream filename;
    3.41    uint32_t n = rand ();
    3.42    filename << n;
    3.43 -  m_testFilename = "/tmp/" + filename.str () + ".pcap";
    3.44 +  m_testFilename = GetTempDir () + filename.str () + ".pcap";
    3.45  }
    3.46  
    3.47  void
     4.1 --- a/src/contrib/net-anim/animation-interface.cc	Mon Nov 09 13:32:18 2009 -0500
     4.2 +++ b/src/contrib/net-anim/animation-interface.cc	Mon Nov 09 13:36:23 2009 -0500
     4.3 @@ -21,9 +21,15 @@
     4.4  #include <stdio.h>
     4.5  #include <sstream>
     4.6  
     4.7 +#include "ns3/net-anim-config.h"
     4.8 +
     4.9  // Socket related includes
    4.10 -#include <sys/socket.h>
    4.11 -#include <netinet/in.h>
    4.12 +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
    4.13 +# include <sys/socket.h>
    4.14 +# include <netinet/in.h>
    4.15 +#else
    4.16 +#include <fcntl.h>
    4.17 +#endif
    4.18  
    4.19  // ns3 includes
    4.20  #include "ns3/animation-interface.h"
    4.21 @@ -58,6 +64,7 @@
    4.22  
    4.23  bool AnimationInterface::SetServerPort (uint16_t port)
    4.24  {
    4.25 +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
    4.26    int s = socket (AF_INET, SOCK_STREAM, 0);
    4.27    struct sockaddr_in addr;
    4.28    addr.sin_family = AF_INET;
    4.29 @@ -77,6 +84,8 @@
    4.30    int t = 1;
    4.31    setsockopt (s, SOL_SOCKET, SO_LINGER, &t, sizeof(t));
    4.32    return true;
    4.33 +#endif
    4.34 +  return false;//never reached unless the above is disabled
    4.35  }
    4.36  
    4.37  bool AnimationInterface::SetInternalAnimation ()
     5.1 --- a/src/contrib/net-anim/point-to-point-dumbbell-helper.cc	Mon Nov 09 13:32:18 2009 -0500
     5.2 +++ b/src/contrib/net-anim/point-to-point-dumbbell-helper.cc	Mon Nov 09 13:36:23 2009 -0500
     5.3 @@ -21,10 +21,6 @@
     5.4  #include <iostream>
     5.5  #include <sstream>
     5.6  
     5.7 -// Socket related includes
     5.8 -#include <sys/socket.h>
     5.9 -#include <netinet/in.h>
    5.10 -
    5.11  // ns3 includes
    5.12  #include "ns3/animation-interface.h"
    5.13  #include "ns3/point-to-point-dumbbell-helper.h"
     6.1 --- a/src/contrib/net-anim/wscript	Mon Nov 09 13:32:18 2009 -0500
     6.2 +++ b/src/contrib/net-anim/wscript	Mon Nov 09 13:36:23 2009 -0500
     6.3 @@ -1,5 +1,11 @@
     6.4  ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
     6.5  
     6.6 +def configure(conf):
     6.7 +    conf.check(header_name='sys/socket.h', define_name='HAVE_SYS_SOCKET_H')
     6.8 +    conf.check(header_name='netinet/in.h', define_name='HAVE_NETINET_IN_H')
     6.9 +    conf.write_config_header('ns3/net-anim-config.h', top=True)
    6.10 +
    6.11 +
    6.12  def build(bld):
    6.13      obj = bld.create_ns3_module('net-anim')
    6.14      obj.source = [
     7.1 --- a/src/contrib/wscript	Mon Nov 09 13:32:18 2009 -0500
     7.2 +++ b/src/contrib/wscript	Mon Nov 09 13:36:23 2009 -0500
     7.3 @@ -14,9 +14,11 @@
     7.4      conf.report_optional_feature("XmlIo", "XmlIo",
     7.5                                   conf.env['ENABLE_LIBXML2'],
     7.6                                   "library 'libxml-2.0 >= 2.7' not found")
     7.7 +    conf.write_config_header('ns3/contrib-config.h', top=True)
     7.8 +
     7.9      conf.sub_config('stats')
    7.10 +    conf.sub_config('net-anim')
    7.11  
    7.12 -    conf.write_config_header('ns3/contrib-config.h', top=True)
    7.13  
    7.14  def build(bld):
    7.15      module = bld.create_ns3_module('contrib', ['simulator', 'common'])
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/core/object-ref-count.h	Mon Nov 09 13:36:23 2009 -0500
     8.3 @@ -0,0 +1,120 @@
     8.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     8.5 +/*
     8.6 + * Copyright (c) 2009 Mathieu Lacage
     8.7 + *
     8.8 + * This program is free software; you can redistribute it and/or modify
     8.9 + * it under the terms of the GNU General Public License version 2 as
    8.10 + * published by the Free Software Foundation;
    8.11 + *
    8.12 + * This program is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU General Public License
    8.18 + * along with this program; if not, write to the Free Software
    8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.20 + *
    8.21 + * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
    8.22 + */
    8.23 +#ifndef OBJECT_REF_COUNT_H
    8.24 +#define OBJECT_REF_COUNT_H
    8.25 +
    8.26 +#include "empty.h"
    8.27 +
    8.28 +namespace ns3 {
    8.29 +
    8.30 +/**
    8.31 + * This templated class provides the refcounting implementation
    8.32 + * for the ns3::Object class.
    8.33 + *
    8.34 + * The tricky aspect of the implementation of this class is that
    8.35 + * instead of storing a count directly, it keeps track of a pointer
    8.36 + * to a count to allow multiple instances of the class to share the
    8.37 + * same pointer/count. This is mainly used by the aggregation support
    8.38 + * of the ns3::Object class
    8.39 + */
    8.40 +template <typename T, typename PARENT = empty>
    8.41 +class ObjectRefCount : public PARENT
    8.42 +{
    8.43 +public:
    8.44 +  ObjectRefCount ()
    8.45 +    : m_count (new int (1))
    8.46 +  {}
    8.47 +  ObjectRefCount (const ObjectRefCount &o)
    8.48 +    : m_count (new int (1))
    8.49 +  {}
    8.50 +  ObjectRefCount & operator = (const ObjectRefCount &o)
    8.51 +  {
    8.52 +    return *this;
    8.53 +  }
    8.54 +  ~ObjectRefCount () 
    8.55 +  {
    8.56 +    m_count = 0;
    8.57 +  }
    8.58 +
    8.59 +  /**
    8.60 +   * Get the reference count of the object.  Normally not needed; for language bindings.
    8.61 +   */
    8.62 +  int GetReferenceCount (void) const {
    8.63 +    return *m_count;
    8.64 +  }
    8.65 +  /**
    8.66 +   * Increment the reference count. This method should not be called
    8.67 +   * by user code. Object instances are expected to be used in conjunction
    8.68 +   * of the Ptr template which would make calling Ref unecessary and 
    8.69 +   * dangerous.
    8.70 +   */
    8.71 +  inline void Ref (void) const
    8.72 +    {
    8.73 +      (*m_count)++;
    8.74 +    }
    8.75 +  /**
    8.76 +   * Decrement the reference count. This method should not be called
    8.77 +   * by user code. Object instances are expected to be used in conjunction
    8.78 +   * of the Ptr template which would make calling Ref unecessary and 
    8.79 +   * dangerous.
    8.80 +   */
    8.81 +  inline void Unref (void) const
    8.82 +    {
    8.83 +      (*m_count)--;
    8.84 +      if ((*m_count) == 0)
    8.85 +        {
    8.86 +	  const_cast<ObjectRefCount<T,PARENT>*>(this)->DoDelete ();
    8.87 +        }
    8.88 +    }
    8.89 +protected:
    8.90 +  /**
    8.91 +   * \param other another object
    8.92 +   *
    8.93 +   * This method makes this object and the input other object
    8.94 +   * share the same reference count.
    8.95 +   */
    8.96 +  void ShareCount (ObjectRefCount *other)
    8.97 +    {
    8.98 +      (*m_count) += (*other->m_count);
    8.99 +      delete other->m_count;
   8.100 +      other->m_count = m_count;
   8.101 +    }
   8.102 +  /**
   8.103 +   * Called just before deleting this object: when two
   8.104 +   * objects share the same reference count, the user
   8.105 +   * who is deleting them must be careful to delete the
   8.106 +   * associated count only once and this is done by calling 
   8.107 +   * this method to get a reference to the count and, then,
   8.108 +   * calling delete on the count.
   8.109 +   *
   8.110 +   * \sa ns3::Object::DoDelete
   8.111 +   */
   8.112 +  int *PeekCountPtr (void) const
   8.113 +    {
   8.114 +      return m_count;
   8.115 +    }
   8.116 +private:
   8.117 +  virtual void DoDelete (void) = 0;
   8.118 +  mutable int *m_count;
   8.119 +};
   8.120 +
   8.121 +} // namespace ns3
   8.122 +
   8.123 +#endif /* OBJECT_REF_COUNT_H */
     9.1 --- a/src/core/object.cc	Mon Nov 09 13:32:18 2009 -0500
     9.2 +++ b/src/core/object.cc	Mon Nov 09 13:36:23 2009 -0500
     9.3 @@ -28,6 +28,8 @@
     9.4  #include "string.h"
     9.5  #include <vector>
     9.6  #include <sstream>
     9.7 +#include <stdlib.h>
     9.8 +#include <string.h>
     9.9  
    9.10  NS_LOG_COMPONENT_DEFINE ("Object");
    9.11  
    9.12 @@ -40,28 +42,23 @@
    9.13  NS_OBJECT_ENSURE_REGISTERED (Object);
    9.14  
    9.15  Object::AggregateIterator::AggregateIterator ()
    9.16 -  : m_first (0),
    9.17 +  : m_object (0),
    9.18      m_current (0)
    9.19  {}
    9.20  
    9.21  bool 
    9.22  Object::AggregateIterator::HasNext (void) const
    9.23  {
    9.24 -  if (m_current != 0 && m_current->m_next != PeekPointer (m_first))
    9.25 -    {
    9.26 -      return true;
    9.27 -    }
    9.28 -  return false;
    9.29 +  return m_current < m_object->m_aggregates->n;
    9.30  }
    9.31  Ptr<const Object> 
    9.32  Object::AggregateIterator::Next (void)
    9.33  {
    9.34 -  m_current = m_current->m_next;
    9.35 -  return m_current;
    9.36 +  return m_object->m_aggregates->buffer[m_current];
    9.37  }
    9.38 -Object::AggregateIterator::AggregateIterator (Ptr<const Object> first)
    9.39 -  : m_first (first),
    9.40 -    m_current (first)
    9.41 +Object::AggregateIterator::AggregateIterator (Ptr<const Object> object)
    9.42 +  : m_object (object),
    9.43 +    m_current (0)
    9.44  {}
    9.45  
    9.46  
    9.47 @@ -82,25 +79,45 @@
    9.48  
    9.49  
    9.50  Object::Object ()
    9.51 -  : m_count (1),
    9.52 -    m_tid (Object::GetTypeId ()),
    9.53 +  : m_tid (Object::GetTypeId ()),
    9.54      m_disposed (false),
    9.55 -    m_next (this)
    9.56 -{}
    9.57 +    m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
    9.58 +    m_getObjectCount (0)
    9.59 +{
    9.60 +  m_aggregates->n = 1;
    9.61 +  m_aggregates->buffer[0] = this;
    9.62 +}
    9.63  Object::~Object () 
    9.64  {
    9.65 -  m_next = 0;
    9.66 +  // remove this object from the aggregate list
    9.67 +  uint32_t n = m_aggregates->n;
    9.68 +  for (uint32_t i = 0; i < n; i++)
    9.69 +    {
    9.70 +      Object *current = m_aggregates->buffer[i];
    9.71 +      if (current == this)
    9.72 +        {
    9.73 +          memmove (&m_aggregates->buffer[i], 
    9.74 +                   &m_aggregates->buffer[i+1],
    9.75 +                   sizeof (Object *)*(m_aggregates->n - (i+1)));
    9.76 +          m_aggregates->n--;
    9.77 +        }
    9.78 +    }
    9.79 +  // finally, if all objects have been removed from the list,
    9.80 +  // delete the aggregate list
    9.81 +  if (m_aggregates->n == 0)
    9.82 +    {
    9.83 +      free (m_aggregates);
    9.84 +    }
    9.85 +  m_aggregates = 0;
    9.86  }
    9.87  Object::Object (const Object &o)
    9.88 -  : m_count (1),
    9.89 -    m_tid (o.m_tid),
    9.90 +  : m_tid (o.m_tid),
    9.91      m_disposed (false),
    9.92 -    m_next (this)
    9.93 -{}
    9.94 -uint32_t
    9.95 -Object::GetReferenceCount (void) const
    9.96 +    m_aggregates ((struct Aggregates *)malloc (sizeof (struct Aggregates))),
    9.97 +    m_getObjectCount (0)
    9.98  {
    9.99 -  return m_count;
   9.100 +  m_aggregates->n = 1;
   9.101 +  m_aggregates->buffer[0] = this;
   9.102  }
   9.103  void
   9.104  Object::Construct (const AttributeList &attributes)
   9.105 @@ -112,34 +129,58 @@
   9.106  Object::DoGetObject (TypeId tid) const
   9.107  {
   9.108    NS_ASSERT (CheckLoose ());
   9.109 -  const Object *currentObject = this;
   9.110 +
   9.111 +  uint32_t n = m_aggregates->n;
   9.112    TypeId objectTid = Object::GetTypeId ();
   9.113 -  do {
   9.114 -    NS_ASSERT (currentObject != 0);
   9.115 -    TypeId cur = currentObject->GetInstanceTypeId ();
   9.116 -    while (cur != tid && cur != objectTid)
   9.117 -      {
   9.118 -        cur = cur.GetParent ();
   9.119 -      }
   9.120 -    if (cur == tid)
   9.121 -      {
   9.122 -        return const_cast<Object *> (currentObject);
   9.123 -      }
   9.124 -    currentObject = currentObject->m_next;
   9.125 -  } while (currentObject != this);
   9.126 +  for (uint32_t i = 0; i < n; i++)
   9.127 +    {
   9.128 +      Object *current = m_aggregates->buffer[i];
   9.129 +      TypeId cur = current->GetInstanceTypeId ();
   9.130 +      while (cur != tid && cur != objectTid)
   9.131 +        {
   9.132 +          cur = cur.GetParent ();
   9.133 +        }
   9.134 +      if (cur == tid)
   9.135 +        {
   9.136 +          // This is an attempt to 'cache' the result of this lookup.
   9.137 +          // the idea is that if we perform a lookup for a TypeId on this object,
   9.138 +          // we are likely to perform the same lookup later so, we make sure
   9.139 +          // that the aggregate array is sorted by the number of accesses
   9.140 +          // to each object.
   9.141 +
   9.142 +          // first, increment the access count
   9.143 +          current->m_getObjectCount++;
   9.144 +          // then, update the sort
   9.145 +          UpdateSortedArray (m_aggregates, i);
   9.146 +          // finally, return the match
   9.147 +          return const_cast<Object *> (current);
   9.148 +        }
   9.149 +    }
   9.150    return 0;
   9.151  }
   9.152  void 
   9.153  Object::Dispose (void)
   9.154  {
   9.155 -  Object *current = this;
   9.156 -  do {
   9.157 -    NS_ASSERT (current != 0);
   9.158 -    NS_ASSERT (!current->m_disposed);
   9.159 -    current->DoDispose ();
   9.160 -    current->m_disposed = true;
   9.161 -    current = current->m_next;
   9.162 -  } while (current != this);
   9.163 +  uint32_t n = m_aggregates->n;
   9.164 +  for (uint32_t i = 0; i < n; i++)
   9.165 +    {
   9.166 +      Object *current = m_aggregates->buffer[i];
   9.167 +      NS_ASSERT (!current->m_disposed);
   9.168 +      current->DoDispose ();
   9.169 +      current->m_disposed = true;
   9.170 +    }
   9.171 +}
   9.172 +void
   9.173 +Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
   9.174 +{
   9.175 +  while (j > 0 && 
   9.176 +         aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount)
   9.177 +    {
   9.178 +      Object *tmp = aggregates->buffer[j-1];
   9.179 +      aggregates->buffer[j-1] = aggregates->buffer[j];
   9.180 +      aggregates->buffer[j] = tmp;
   9.181 +      j--;
   9.182 +    }
   9.183  }
   9.184  void 
   9.185  Object::AggregateObject (Ptr<Object> o)
   9.186 @@ -157,20 +198,42 @@
   9.187      }
   9.188  
   9.189    Object *other = PeekPointer (o);
   9.190 -  Object *next = m_next;
   9.191 -  m_next = other->m_next;
   9.192 -  other->m_next = next;
   9.193 -  NS_ASSERT (CheckLoose ());
   9.194 -  NS_ASSERT (o->CheckLoose ());
   9.195 -  // call NotifyNewAggregate in the listed chain
   9.196 -  Object *currentObject = this;
   9.197 -  do 
   9.198 +  // first create the new aggregate buffer.
   9.199 +  uint32_t total = m_aggregates->n + other->m_aggregates->n;
   9.200 +  struct Aggregates *aggregates = 
   9.201 +    (struct Aggregates *)malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*));
   9.202 +  aggregates->n = total;
   9.203 +  memcpy (&aggregates->buffer[0], 
   9.204 +          &m_aggregates->buffer[0], 
   9.205 +          m_aggregates->n*sizeof(Object*));
   9.206 +  // append the other aggregates in the new buffer
   9.207 +  for (uint32_t i = 0; i < other->m_aggregates->n; i++)
   9.208      {
   9.209 -      // the NotifyNewAggregate of the current object implementation
   9.210 -      // should be called on the next object in the linked chain
   9.211 -      currentObject->NotifyNewAggregate ();
   9.212 -      currentObject = currentObject->m_next;
   9.213 -    } while (currentObject != this);
   9.214 +      aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i];
   9.215 +      UpdateSortedArray (aggregates, m_aggregates->n + i);
   9.216 +    }
   9.217 +
   9.218 +  // free both aggregate buffers
   9.219 +  free (m_aggregates);
   9.220 +  free (other->m_aggregates);
   9.221 +
   9.222 +  // Then, assign that buffer to every object
   9.223 +  uint32_t n = aggregates->n;
   9.224 +  for (uint32_t i = 0; i < n; i++)
   9.225 +    {
   9.226 +      Object *current = aggregates->buffer[i];
   9.227 +      current->m_aggregates = aggregates;
   9.228 +    }
   9.229 +
   9.230 +  // share the counts
   9.231 +  ShareCount (other);
   9.232 +
   9.233 +  // Finally, call NotifyNewAggregate in the listed chain
   9.234 +  for (uint32_t i = 0; i < n; i++)
   9.235 +    {
   9.236 +      Object *current = m_aggregates->buffer[i];
   9.237 +      current->NotifyNewAggregate ();
   9.238 +    }
   9.239  }
   9.240  /**
   9.241   * This function must be implemented in the stack that needs to notify
   9.242 @@ -205,7 +268,7 @@
   9.243  bool 
   9.244  Object::Check (void) const
   9.245  {
   9.246 -  return (m_count > 0);
   9.247 +  return (GetReferenceCount () > 0);
   9.248  }
   9.249  
   9.250  /* In some cases, when an event is scheduled against a subclass of
   9.251 @@ -219,54 +282,43 @@
   9.252  Object::CheckLoose (void) const
   9.253  {
   9.254    uint32_t refcount = 0;
   9.255 -  const Object *current = this;
   9.256 -  do
   9.257 +  uint32_t n = m_aggregates->n;
   9.258 +  for (uint32_t i = 0; i < n; i++)
   9.259      {
   9.260 -      refcount += current->m_count;
   9.261 -      current = current->m_next;
   9.262 +      Object *current = m_aggregates->buffer[i];
   9.263 +      refcount += current->GetReferenceCount ();
   9.264      }
   9.265 -  while (current != this);
   9.266 -
   9.267    return (refcount > 0);
   9.268  }
   9.269 +void
   9.270 +Object::DoDelete (void)
   9.271 +{
   9.272 +  uint32_t n = m_aggregates->n;
   9.273 +  // Ensure we are disposed.
   9.274 +  for (uint32_t i = 0; i < n; i++)
   9.275 +    {
   9.276 +      Object *current = m_aggregates->buffer[i];
   9.277 +      if (!current->m_disposed)
   9.278 +        {
   9.279 +          current->DoDispose ();
   9.280 +        }
   9.281 +    }
   9.282  
   9.283 -void
   9.284 -Object::MaybeDelete (void) const
   9.285 -{
   9.286 -  // First, check if any of the attached
   9.287 -  // Object has a non-zero count.
   9.288 -  const Object *current = this;
   9.289 -  do {
   9.290 -    NS_ASSERT (current != 0);
   9.291 -    if (current->m_count != 0)
   9.292 -      {
   9.293 -        return;
   9.294 -      }
   9.295 -    current = current->m_next;
   9.296 -  } while (current != this);
   9.297 +  int *count = PeekCountPtr ();
   9.298  
   9.299 -  // Ensure we are disposed.
   9.300 -  Object *tmp = const_cast<Object *> (this);
   9.301 -  const Object *end = this;
   9.302 -  do {
   9.303 -    NS_ASSERT (current != 0);
   9.304 -    Object *next = tmp->m_next;
   9.305 -    if (!tmp->m_disposed)
   9.306 -      {
   9.307 -        tmp->DoDispose ();
   9.308 -      }
   9.309 -    tmp = next;
   9.310 -  } while (tmp != end);
   9.311 +  // Now, actually delete all objects
   9.312 +  struct Aggregates *aggregates = m_aggregates;
   9.313 +  for (uint32_t i = 0; i < n; i++)
   9.314 +    {
   9.315 +      // There is a trick here: each time we call delete below,
   9.316 +      // the deleted object is removed from the aggregate buffer
   9.317 +      // in the destructor so, the index of the next element to 
   9.318 +      // lookup is always zero
   9.319 +      Object *current = aggregates->buffer[0];
   9.320 +      delete current;
   9.321 +    }
   9.322  
   9.323 -  // all attached objects have a zero count so, 
   9.324 -  // we can delete all attached objects.
   9.325 -  current = this;
   9.326 -  do {
   9.327 -    NS_ASSERT (current != 0);
   9.328 -    Object *next = current->m_next;
   9.329 -    delete current;
   9.330 -    current = next;
   9.331 -  } while (current != end);
   9.332 +  delete count;
   9.333  }
   9.334  } // namespace ns3
   9.335  
    10.1 --- a/src/core/object.h	Mon Nov 09 13:32:18 2009 -0500
    10.2 +++ b/src/core/object.h	Mon Nov 09 13:36:23 2009 -0500
    10.3 @@ -28,6 +28,7 @@
    10.4  #include "attribute.h"
    10.5  #include "object-base.h"
    10.6  #include "attribute-list.h"
    10.7 +#include "object-ref-count.h"
    10.8  
    10.9  
   10.10  namespace ns3 {
   10.11 @@ -55,7 +56,7 @@
   10.12   * invoked from the Object::Unref method before destroying the object, even if the user 
   10.13   * did not call Object::Dispose directly.
   10.14   */
   10.15 -class Object : public ObjectBase
   10.16 +class Object : public ObjectRefCount<Object,ObjectBase>
   10.17  {
   10.18  public:
   10.19    static TypeId GetTypeId (void);
   10.20 @@ -85,9 +86,9 @@
   10.21      Ptr<const Object> Next (void);
   10.22    private:
   10.23      friend class Object;
   10.24 -    AggregateIterator (Ptr<const Object> first);
   10.25 -    Ptr<const Object> m_first;
   10.26 -    Ptr<const Object> m_current;
   10.27 +    AggregateIterator (Ptr<const Object> object);
   10.28 +    Ptr<const Object> m_object;
   10.29 +    uint32_t m_current;
   10.30    };
   10.31  
   10.32    Object ();
   10.33 @@ -99,30 +100,10 @@
   10.34    virtual TypeId GetInstanceTypeId (void) const;
   10.35  
   10.36    /**
   10.37 -   * Increment the reference count. This method should not be called
   10.38 -   * by user code. Object instances are expected to be used in conjunction
   10.39 -   * of the Ptr template which would make calling Ref unecessary and 
   10.40 -   * dangerous.
   10.41 -   */
   10.42 -  inline void Ref (void) const;
   10.43 -  /**
   10.44 -   * Decrement the reference count. This method should not be called
   10.45 -   * by user code. Object instances are expected to be used in conjunction
   10.46 -   * of the Ptr template which would make calling Ref unecessary and 
   10.47 -   * dangerous.
   10.48 -   */
   10.49 -  inline void Unref (void) const;
   10.50 -
   10.51 -  /**
   10.52 -   * Get the reference count of the object.  Normally not needed; for language bindings.
   10.53 -   */
   10.54 -  uint32_t GetReferenceCount (void) const;
   10.55 -
   10.56 -  /**
   10.57     * \returns a pointer to the requested interface or zero if it could not be found.
   10.58     */
   10.59    template <typename T>
   10.60 -  Ptr<T> GetObject (void) const;
   10.61 +  inline Ptr<T> GetObject (void) const;
   10.62    /**
   10.63     * \param tid the interface id of the requested interface
   10.64     * \returns a pointer to the requested interface or zero if it could not be found.
   10.65 @@ -215,17 +196,25 @@
   10.66    friend class ObjectFactory;
   10.67    friend class AggregateIterator;
   10.68  
   10.69 +  /**
   10.70 +   * This data structure uses a classic C-style trick to 
   10.71 +   * hold an array of variable size without performing
   10.72 +   * two memory allocations: the declaration of the structure
   10.73 +   * declares a one-element array but when we allocate
   10.74 +   * memory for this struct, we effectively allocate a larger
   10.75 +   * chunk of memory than the struct to allow space for a larger
   10.76 +   * variable sized buffer whose size is indicated by the element
   10.77 +   * 'n'
   10.78 +   */
   10.79 +  struct Aggregates {
   10.80 +    uint32_t n;
   10.81 +    Object *buffer[1];
   10.82 +  };
   10.83 +
   10.84    Ptr<Object> DoGetObject (TypeId tid) const;
   10.85    bool Check (void) const;
   10.86    bool CheckLoose (void) const;
   10.87    /**
   10.88 -   * Attempt to delete this object. This method iterates
   10.89 -   * over all aggregated objects to check if they all 
   10.90 -   * have a zero refcount. If yes, the object and all
   10.91 -   * its aggregates are deleted. If not, nothing is done.
   10.92 -   */
   10.93 -  void MaybeDelete (void) const;
   10.94 -  /**
   10.95     * \param tid an TypeId
   10.96     *
   10.97     * Invoked from ns3::CreateObject only.
   10.98 @@ -243,14 +232,15 @@
   10.99     */
  10.100    void Construct (const AttributeList &attributes);
  10.101  
  10.102 +  void UpdateSortedArray (struct Aggregates *aggregates, uint32_t i) const;
  10.103    /**
  10.104 -   * The reference count for this object. Each aggregate
  10.105 -   * has an individual reference count. When the global
  10.106 -   * reference count (the sum of all reference counts) 
  10.107 -   * reaches zero, the object and all its aggregates is 
  10.108 -   * deleted.
  10.109 +   * Attempt to delete this object. This method iterates
  10.110 +   * over all aggregated objects to check if they all 
  10.111 +   * have a zero refcount. If yes, the object and all
  10.112 +   * its aggregates are deleted. If not, nothing is done.
  10.113     */
  10.114 -  mutable uint32_t m_count;
  10.115 +  virtual void DoDelete (void);
  10.116 +
  10.117    /**
  10.118     * Identifies the type of this object instance.
  10.119     */
  10.120 @@ -261,13 +251,19 @@
  10.121     */
  10.122    bool m_disposed;
  10.123    /**
  10.124 -   * A pointer to the next aggregate object. This is a circular
  10.125 -   * linked list of aggregated objects: the last one points
  10.126 -   * back to the first one. If an object is not aggregated to
  10.127 -   * any other object, the value of this field is equal to the
  10.128 -   * value of the 'this' pointer.
  10.129 +   * a pointer to an array of 'aggregates'. i.e., a pointer to
  10.130 +   * each object aggregated to this object is stored in this 
  10.131 +   * array. The array is shared by all aggregated objects
  10.132 +   * so the size of the array is indirectly a reference count.
  10.133     */
  10.134 -  Object *m_next;
  10.135 +  struct Aggregates * m_aggregates;
  10.136 +  /**
  10.137 +   * Indicates the number of times the object was accessed with a
  10.138 +   * call to GetObject. This integer is used to implement a
  10.139 +   * heuristic to sort the array of aggregates to put at the start
  10.140 +   * of the array the most-frequently accessed elements.
  10.141 +   */
  10.142 +  uint32_t m_getObjectCount;
  10.143  };
  10.144  
  10.145  /**
  10.146 @@ -340,26 +336,15 @@
  10.147   *   The Object implementation which depends on templates
  10.148   *************************************************************************/
  10.149  
  10.150 -void
  10.151 -Object::Ref (void) const
  10.152 -{
  10.153 -  m_count++;
  10.154 -}
  10.155 -void
  10.156 -Object::Unref (void) const
  10.157 -{
  10.158 -  NS_ASSERT (Check ());
  10.159 -  m_count--;
  10.160 -  if (m_count == 0)
  10.161 -    {
  10.162 -      MaybeDelete ();
  10.163 -    }
  10.164 -}
  10.165 -
  10.166  template <typename T>
  10.167  Ptr<T> 
  10.168  Object::GetObject () const
  10.169  {
  10.170 +  T *result = dynamic_cast<T *> (m_aggregates->buffer[0]);
  10.171 +  if (result != 0)
  10.172 +    {
  10.173 +      return Ptr<T> (result);
  10.174 +    }
  10.175    Ptr<Object> found = DoGetObject (T::GetTypeId ());
  10.176    if (found != 0)
  10.177      {
    11.1 --- a/src/core/test.cc	Mon Nov 09 13:32:18 2009 -0500
    11.2 +++ b/src/core/test.cc	Mon Nov 09 13:36:23 2009 -0500
    11.3 @@ -87,6 +87,7 @@
    11.4      m_continueOnFailure (false), 
    11.5      m_detailsReported (false), 
    11.6      m_basedir ("invalid"), 
    11.7 +    m_tempdir ("invalid"), 
    11.8      m_ofs (0), 
    11.9      m_error (false)
   11.10  {
   11.11 @@ -203,7 +204,18 @@
   11.12  void 
   11.13  TestCase::SetBaseDir (std::string basedir)
   11.14  {
   11.15 -  m_basedir = basedir;
   11.16 +  //
   11.17 +  // C and C++ allow one to use forward slashes even on systems where the 
   11.18 +  // separator is actually a backslash.
   11.19 +  //
   11.20 +  if (basedir[basedir.length () - 1] != '/')
   11.21 +    {
   11.22 +      m_basedir = basedir + "/";
   11.23 +    }
   11.24 +  else
   11.25 +    {
   11.26 +      m_basedir = basedir;
   11.27 +    }
   11.28  }
   11.29  
   11.30  std::string 
   11.31 @@ -212,13 +224,52 @@
   11.32    return m_basedir;
   11.33  }
   11.34  
   11.35 +void 
   11.36 +TestCase::SetTempDir (std::string tempdir)
   11.37 +{
   11.38 +  //
   11.39 +  // C and C++ allow one to use forward slashes even on systems where the 
   11.40 +  // separator is actually a backslash.
   11.41 +  //
   11.42 +  if (tempdir[tempdir.length () - 1] != '/')
   11.43 +    {
   11.44 +      m_tempdir = tempdir + "/";
   11.45 +    }
   11.46 +  else
   11.47 +    {
   11.48 +      m_tempdir = tempdir;
   11.49 +    }
   11.50 +}
   11.51 +
   11.52 +std::string 
   11.53 +TestCase::GetTempDir (void)
   11.54 +{
   11.55 +  return m_tempdir;
   11.56 +}
   11.57 +
   11.58  std::string 
   11.59  TestCase::GetSourceDir (std::string file)
   11.60  {
   11.61 +  //
   11.62 +  // The <file> parameter is actually going to be __FILE__ which may have 
   11.63 +  // backslashes in it on win32 systems.  For example,
   11.64 +  //
   11.65 +  //   ..\src\common\pcap-file-test-suite.cc  (win32)
   11.66 +  //
   11.67 +  // or
   11.68 +  //
   11.69 +  //   ../src/common/pcap-file-test-suite.cc  (grown-up systems)
   11.70 +  //
   11.71 +#ifdef WIN32
   11.72 +  std::string::size_type relPathBegin = file.find_first_of ("\\");
   11.73 +  std::string::size_type relPathEnd = file.find_last_of ("\\");
   11.74 +#else
   11.75    std::string::size_type relPathBegin = file.find_first_of ("/");
   11.76 -  NS_ABORT_MSG_IF (relPathBegin == std::string::npos, "TestCase::GetSrouceDir(): Internal Error");
   11.77    std::string::size_type relPathEnd = file.find_last_of ("/");
   11.78 -  NS_ABORT_MSG_IF (relPathEnd == std::string::npos, "TestCase::GetSrouceDir(): Internal Error");
   11.79 +#endif
   11.80 +
   11.81 +  NS_ABORT_MSG_IF (relPathBegin == std::string::npos, "TestCase::GetSourceDir(): Internal Error");
   11.82 +  NS_ABORT_MSG_IF (relPathEnd == std::string::npos, "TestCase::GetSourceDir(): Internal Error");
   11.83  
   11.84    return GetBaseDir () + file.substr (relPathBegin, relPathEnd + 1 - relPathBegin);
   11.85  }
   11.86 @@ -353,6 +404,7 @@
   11.87    : m_name (name), 
   11.88      m_verbose (false), 
   11.89      m_basedir ("invalid"), 
   11.90 +    m_tempdir ("invalid"), 
   11.91      m_ofs (0), 
   11.92      m_error (false), 
   11.93      m_type (type)
   11.94 @@ -476,7 +528,18 @@
   11.95  void 
   11.96  TestSuite::SetBaseDir (std::string basedir)
   11.97  {
   11.98 -  m_basedir = basedir;
   11.99 +  //
  11.100 +  // C and C++ allow one to use forward slashes even on systems where the 
  11.101 +  // separator is actually a backslash.
  11.102 +  //
  11.103 +  if (basedir[basedir.length () - 1] != '/')
  11.104 +    {
  11.105 +      m_basedir = basedir + "/";
  11.106 +    }
  11.107 +  else
  11.108 +    {
  11.109 +      m_basedir = basedir;
  11.110 +    }
  11.111  }
  11.112  
  11.113  std::string 
  11.114 @@ -486,6 +549,29 @@
  11.115  }
  11.116  
  11.117  void 
  11.118 +TestSuite::SetTempDir (std::string tempdir)
  11.119 +{
  11.120 +  //
  11.121 +  // C and C++ allow one to use forward slashes even on systems where the 
  11.122 +  // separator is actually a backslash.
  11.123 +  //
  11.124 +  if (tempdir[tempdir.length () - 1] != '/')
  11.125 +    {
  11.126 +      m_tempdir = tempdir + "/";
  11.127 +    }
  11.128 +  else
  11.129 +    {
  11.130 +      m_tempdir = tempdir;
  11.131 +    }
  11.132 +}
  11.133 +
  11.134 +std::string 
  11.135 +TestSuite::GetTempDir (void)
  11.136 +{
  11.137 +  return m_tempdir;
  11.138 +}
  11.139 +
  11.140 +void 
  11.141  TestSuite::SetStream (std::ofstream *ofs)
  11.142  {
  11.143    m_ofs = ofs;
  11.144 @@ -589,6 +675,7 @@
  11.145        (*i)->SetVerbose (m_verbose);
  11.146        (*i)->SetContinueOnFailure (m_continueOnFailure);
  11.147        (*i)->SetBaseDir (m_basedir);
  11.148 +      (*i)->SetTempDir (m_tempdir);
  11.149        (*i)->SetStream (m_ofs);
  11.150  
  11.151        //
    12.1 --- a/src/core/test.h	Mon Nov 09 13:32:18 2009 -0500
    12.2 +++ b/src/core/test.h	Mon Nov 09 13:36:23 2009 -0500
    12.3 @@ -662,6 +662,16 @@
    12.4     */
    12.5    std::string GetBaseDir (void);
    12.6  
    12.7 +  /**
    12.8 +   * \brief Set the temporary file directory (where to write temporary files).
    12.9 +   */
   12.10 +  void SetTempDir (std::string dir);
   12.11 +
   12.12 +  /**
   12.13 +   * \brief Get the temporary file directory .
   12.14 +   */
   12.15 +  std::string GetTempDir (void);
   12.16 +
   12.17  /**
   12.18   * \brief Get the source directory of the current source file.
   12.19   *
   12.20 @@ -830,6 +840,7 @@
   12.21    bool m_continueOnFailure;
   12.22    bool m_detailsReported;
   12.23    std::string m_basedir;
   12.24 +  std::string m_tempdir;
   12.25    std::ofstream *m_ofs;
   12.26    bool m_error;
   12.27  };
   12.28 @@ -945,6 +956,16 @@
   12.29    std::string GetBaseDir (void);
   12.30  
   12.31    /**
   12.32 +   * \brief Set the temporary file directory (where to write temporary files).
   12.33 +   */
   12.34 +  void SetTempDir (std::string dir);
   12.35 +
   12.36 +  /**
   12.37 +   * \brief Get the temporary file directory.
   12.38 +   */
   12.39 +  std::string GetTempDir (void);
   12.40 +
   12.41 +  /**
   12.42     * \brief Set the stream to which status and result messages will be written.
   12.43     *
   12.44     * We really don't want to have to pass an ofstream around to every function
   12.45 @@ -1064,6 +1085,7 @@
   12.46    bool m_verbose;
   12.47    bool m_continueOnFailure;
   12.48    std::string m_basedir;
   12.49 +  std::string m_tempdir;
   12.50    std::ofstream *m_ofs;
   12.51    bool m_error;
   12.52    TestType m_type;
    13.1 --- a/src/core/wscript	Mon Nov 09 13:32:18 2009 -0500
    13.2 +++ b/src/core/wscript	Mon Nov 09 13:36:23 2009 -0500
    13.3 @@ -126,6 +126,7 @@
    13.4          'abort.h',
    13.5          'names.h',
    13.6          'vector.h',
    13.7 +        'object-ref-count.h',
    13.8          ]
    13.9  
   13.10      if sys.platform == 'win32':
    14.1 --- a/src/devices/mesh/dot11s/dot11s-test-suite.cc	Mon Nov 09 13:32:18 2009 -0500
    14.2 +++ b/src/devices/mesh/dot11s/dot11s-test-suite.cc	Mon Nov 09 13:36:23 2009 -0500
    14.3 @@ -174,9 +174,9 @@
    14.4  {
    14.5    for (std::vector<Mac48Address>::const_iterator i = precursors.begin (); i != precursors.end (); i++)
    14.6      {
    14.7 -      table->AddPrecursor (dst, iface, *i);
    14.8 +      table->AddPrecursor (dst, iface, *i, Seconds (100));
    14.9        // Check that duplicates are filtered
   14.10 -      table->AddPrecursor (dst, iface, *i);
   14.11 +      table->AddPrecursor (dst, iface, *i, Seconds (100));
   14.12      }
   14.13  }
   14.14  
    15.1 --- a/src/devices/mesh/dot11s/hwmp-protocol.cc	Mon Nov 09 13:32:18 2009 -0500
    15.2 +++ b/src/devices/mesh/dot11s/hwmp-protocol.cc	Mon Nov 09 13:36:23 2009 -0500
    15.3 @@ -401,6 +401,7 @@
    15.4    //acceptance cretirea:
    15.5    std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
    15.6        preq.GetOriginatorAddress ());
    15.7 +  bool freshInfo (true);
    15.8    if (i != m_hwmpSeqnoMetricDatabase.end ())
    15.9      {
   15.10        if ((int32_t)(i->second.first - preq.GetOriginatorSeqNumber ())  > 0)
   15.11 @@ -409,21 +410,25 @@
   15.12          }
   15.13        if (i->second.first == preq.GetOriginatorSeqNumber ())
   15.14          {
   15.15 +          freshInfo = false;
   15.16            if (i->second.second <= preq.GetMetric ())
   15.17              {
   15.18                return;
   15.19              }
   15.20          }
   15.21      }
   15.22 -  m_hwmpSeqnoMetricDatabase[preq.GetOriginatorAddress ()] = std::make_pair (preq.GetOriginatorSeqNumber (), preq.GetMetric ());
   15.23 -
   15.24 +  m_hwmpSeqnoMetricDatabase[preq.GetOriginatorAddress ()] =
   15.25 +    std::make_pair (preq.GetOriginatorSeqNumber (), preq.GetMetric ());
   15.26    NS_LOG_DEBUG("I am " << GetAddress () << "Accepted preq from address" << from << ", preq:" << preq);
   15.27    std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
   15.28    //Add reactive path to originator:
   15.29    if (
   15.30 -      ((m_rtable->LookupReactive (preq.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
   15.31 -      ((m_rtable->LookupReactive (preq.GetOriginatorAddress ())).metric > preq.GetMetric ())
   15.32 +      (freshInfo) ||
   15.33 +      (
   15.34 +        (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).retransmitter == Mac48Address::GetBroadcast ()) ||
   15.35 +        (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).metric > preq.GetMetric ())
   15.36        )
   15.37 +     )
   15.38      {
   15.39        m_rtable->AddReactivePath (
   15.40            preq.GetOriginatorAddress (),
   15.41 @@ -432,13 +437,12 @@
   15.42            preq.GetMetric (),
   15.43            MicroSeconds (preq.GetLifetime () * 1024),
   15.44            preq.GetOriginatorSeqNumber ()
   15.45 -          );
   15.46 +        );
   15.47        ReactivePathResolved (preq.GetOriginatorAddress ());
   15.48      }
   15.49 -  //Add reactive path for precursor:
   15.50    if (
   15.51 -      ((m_rtable->LookupReactive (fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
   15.52 -      ((m_rtable->LookupReactive (fromMp)).metric > preq.GetMetric ())
   15.53 +      (m_rtable->LookupReactive (fromMp).retransmitter == Mac48Address::GetBroadcast ()) ||
   15.54 +      (m_rtable->LookupReactive (fromMp).metric > metric)
   15.55        )
   15.56      {
   15.57        m_rtable->AddReactivePath (
   15.58 @@ -477,15 +481,6 @@
   15.59                    preq.GetOriginatorSeqNumber ()
   15.60                    );
   15.61                ProactivePathResolved ();
   15.62 -              m_rtable->AddReactivePath (
   15.63 -                  preq.GetOriginatorAddress (),
   15.64 -                  from,
   15.65 -                  interface,
   15.66 -                  preq.GetMetric (),
   15.67 -                  MicroSeconds (preq.GetLifetime () * 1024),
   15.68 -                  preq.GetOriginatorSeqNumber ()
   15.69 -                  );
   15.70 -              ReactivePathResolved (preq.GetOriginatorAddress ());
   15.71              }
   15.72            if (!preq.IsNeedNotPrep ())
   15.73              {
   15.74 @@ -493,7 +488,7 @@
   15.75                    GetAddress (),
   15.76                    preq.GetOriginatorAddress (),
   15.77                    from,
   15.78 -                  preq.GetMetric (),
   15.79 +                  (uint32_t)0,
   15.80                    preq.GetOriginatorSeqNumber (),
   15.81                    GetNextHwmpSeqno (),
   15.82                    preq.GetLifetime (),
   15.83 @@ -523,9 +518,6 @@
   15.84        if ((! ((*i)->IsDo ())) && (result.retransmitter != Mac48Address::GetBroadcast ()))
   15.85          {
   15.86            //have a valid information and can answer
   15.87 -          //!NB: If there is information from peer - set lifetime as
   15.88 -          //we have got from PREQ, and set the rest lifetime of the
   15.89 -          //route if the information is correct
   15.90            uint32_t lifetime = result.lifetime.GetMicroSeconds () / 1024;
   15.91            if ((lifetime > 0) && ((int32_t)(result.seqnum - (*i)->GetDestSeqNumber ()) >= 0))
   15.92              {
   15.93 @@ -539,6 +531,8 @@
   15.94                    lifetime,
   15.95                    interface
   15.96                    );
   15.97 +              m_rtable->AddPrecursor ((*i)->GetDestinationAddress (), interface, from,
   15.98 +                  MicroSeconds (preq.GetLifetime () * 1024));
   15.99                if ((*i)->IsRf ())
  15.100                  {
  15.101                    (*i)->SetFlags (true, false, (*i)->IsUsn ()); //DO = 1, RF = 0
  15.102 @@ -570,38 +564,52 @@
  15.103    //acceptance cretirea:
  15.104    std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
  15.105        prep.GetOriginatorAddress ());
  15.106 -  if ((i != m_hwmpSeqnoMetricDatabase.end ()) && ((int32_t)(i->second.first - prep.GetOriginatorSeqNumber ()) > 0))
  15.107 +  bool freshInfo (true);
  15.108 +  if (i != m_hwmpSeqnoMetricDatabase.end ())
  15.109      {
  15.110 -      return;
  15.111 +      if ((int32_t)(i->second.first - prep.GetOriginatorSeqNumber ()) > 0)
  15.112 +        {
  15.113 +          return;
  15.114 +        }
  15.115 +      if (i->second.first == prep.GetOriginatorSeqNumber ())
  15.116 +        {
  15.117 +          freshInfo = false;
  15.118 +        }
  15.119      }
  15.120    m_hwmpSeqnoMetricDatabase[prep.GetOriginatorAddress ()] = std::make_pair (prep.GetOriginatorSeqNumber (), prep.GetMetric ());
  15.121    //update routing info
  15.122    //Now add a path to destination and add precursor to source
  15.123    NS_LOG_DEBUG ("I am " << GetAddress () << ", received prep from " << prep.GetOriginatorAddress () << ", receiver was:" << from);
  15.124    HwmpRtable::LookupResult result = m_rtable->LookupReactive (prep.GetDestinationAddress ());
  15.125 -  //Add a reactive path only if it is better than existing:
  15.126 +  //Add a reactive path only if seqno is fresher or it improves the
  15.127 +  //metric
  15.128    if (
  15.129 -      ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
  15.130 -      ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
  15.131 +      (freshInfo) ||
  15.132 +      (
  15.133 +       ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
  15.134 +       ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
  15.135        )
  15.136 +     )
  15.137      {
  15.138        m_rtable->AddReactivePath (
  15.139            prep.GetOriginatorAddress (),
  15.140            from,
  15.141            interface,
  15.142            prep.GetMetric (),
  15.143 -          MicroSeconds(prep.GetLifetime () * 1024),
  15.144 +          MicroSeconds (prep.GetLifetime () * 1024),
  15.145            prep.GetOriginatorSeqNumber ());
  15.146 -      m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from);
  15.147 +      m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from,
  15.148 +          MicroSeconds (prep.GetLifetime () * 1024));
  15.149        if (result.retransmitter != Mac48Address::GetBroadcast ())
  15.150          {
  15.151 -          m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter);
  15.152 +          m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter,
  15.153 +              result.lifetime);
  15.154          }
  15.155        ReactivePathResolved (prep.GetOriginatorAddress ());
  15.156      }
  15.157    if (
  15.158        ((m_rtable->LookupReactive (fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
  15.159 -      ((m_rtable->LookupReactive (fromMp)).metric > prep.GetMetric ())
  15.160 +      ((m_rtable->LookupReactive (fromMp)).metric > metric)
  15.161        )
  15.162      {
  15.163        m_rtable->AddReactivePath (
  15.164 @@ -669,7 +677,7 @@
  15.165    prep.SetDestinationAddress (dst);
  15.166    prep.SetDestinationSeqNumber (destinationSN);
  15.167    prep.SetLifetime (lifetime);
  15.168 -  prep.SetMetric (0);
  15.169 +  prep.SetMetric (initMetric);
  15.170    prep.SetOriginatorAddress (src);
  15.171    prep.SetOriginatorSeqNumber (originatorDsn);
  15.172    HwmpProtocolMacMap::const_iterator prep_sender = m_interfaces.find (interface);
    16.1 --- a/src/devices/mesh/dot11s/hwmp-rtable.cc	Mon Nov 09 13:32:18 2009 -0500
    16.2 +++ b/src/devices/mesh/dot11s/hwmp-rtable.cc	Mon Nov 09 13:36:23 2009 -0500
    16.3 @@ -84,11 +84,12 @@
    16.4  }
    16.5  void
    16.6  HwmpRtable::AddPrecursor (Mac48Address destination, uint32_t precursorInterface,
    16.7 -    Mac48Address precursorAddress)
    16.8 +    Mac48Address precursorAddress, Time lifetime)
    16.9  {
   16.10 -  std::pair<uint32_t, Mac48Address> precursor;
   16.11 -  precursor.first = precursorInterface;
   16.12 -  precursor.second = precursorAddress;
   16.13 +  Precursor precursor;
   16.14 +  precursor.interface = precursorInterface;
   16.15 +  precursor.address = precursorAddress;
   16.16 +  precursor.whenExpire = Simulator::Now () + lifetime;
   16.17    std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
   16.18    if (i != m_routes.end ())
   16.19      {
   16.20 @@ -97,9 +98,10 @@
   16.21          {
   16.22            //NB: Only one active route may exist, so do not check
   16.23            //interface ID, just address
   16.24 -          if (i->second.precursors[j].second == precursorAddress)
   16.25 +          if (i->second.precursors[j].address == precursorAddress)
   16.26              {
   16.27                should_add = false;
   16.28 +              i->second.precursors[j].whenExpire = precursor.whenExpire;
   16.29                break;
   16.30              }
   16.31          }
   16.32 @@ -108,17 +110,6 @@
   16.33            i->second.precursors.push_back (precursor);
   16.34          }
   16.35      }
   16.36 -  if (m_root.root == destination)
   16.37 -    {
   16.38 -      for (unsigned int j = 0; j < m_root.precursors.size (); j++)
   16.39 -        {
   16.40 -          if (m_root.precursors[j].second == precursorAddress)
   16.41 -            {
   16.42 -              return;
   16.43 -            }
   16.44 -        }
   16.45 -    }
   16.46 -  m_root.precursors.push_back (precursor);
   16.47  }
   16.48  void
   16.49  HwmpRtable::DeleteProactivePath ()
   16.50 @@ -221,27 +212,12 @@
   16.51    std::map<Mac48Address, ReactiveRoute>::iterator route = m_routes.find (destination);
   16.52    if (route != m_routes.end ())
   16.53      {
   16.54 -      for (unsigned int i = 0; i < route->second.precursors.size (); i++)
   16.55 +      for (std::vector<Precursor>::const_iterator i = route->second.precursors.begin ();
   16.56 +          i != route->second.precursors.end (); i++)
   16.57          {
   16.58 -          retval.push_back (route->second.precursors[i]);
   16.59 -        }
   16.60 -    }
   16.61 -  if (m_root.root == destination)
   16.62 -    {
   16.63 -      for (unsigned int i = 0; i < m_root.precursors.size (); i++)
   16.64 -        {
   16.65 -          bool should_add = true;
   16.66 -          for (unsigned int j = 0; j < retval.size (); j++)
   16.67 +          if (i->whenExpire > Simulator::Now ())
   16.68              {
   16.69 -              if (retval[j].second == m_root.precursors[i].second)
   16.70 -                {
   16.71 -                  should_add = false;
   16.72 -                  break;
   16.73 -                }
   16.74 -            }
   16.75 -          if (should_add)
   16.76 -            {
   16.77 -              retval.push_back (m_root.precursors[i]);
   16.78 +              retval.push_back (std::make_pair(i->interface, i->address));
   16.79              }
   16.80          }
   16.81      }
    17.1 --- a/src/devices/mesh/dot11s/hwmp-rtable.h	Mon Nov 09 13:32:18 2009 -0500
    17.2 +++ b/src/devices/mesh/dot11s/hwmp-rtable.h	Mon Nov 09 13:36:23 2009 -0500
    17.3 @@ -85,7 +85,7 @@
    17.4      Time  lifetime,
    17.5      uint32_t seqnum
    17.6    );
    17.7 -  void AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress);
    17.8 +  void AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress, Time lifetime);
    17.9    PrecursorList GetPrecursors (Mac48Address destination);
   17.10    void DeleteProactivePath ();
   17.11    void DeleteProactivePath (Mac48Address root);
   17.12 @@ -109,6 +109,12 @@
   17.13  
   17.14  private:
   17.15    /// Route found in reactive mode
   17.16 +  struct Precursor
   17.17 +  {
   17.18 +    Mac48Address address;
   17.19 +    uint32_t interface;
   17.20 +    Time whenExpire;
   17.21 +  };
   17.22    struct ReactiveRoute
   17.23    {
   17.24      Mac48Address retransmitter;
   17.25 @@ -116,7 +122,7 @@
   17.26      uint32_t metric;
   17.27      Time whenExpire;
   17.28      uint32_t seqnum;
   17.29 -    std::vector<std::pair<uint32_t, Mac48Address> > precursors;
   17.30 +    std::vector<Precursor> precursors;
   17.31    };
   17.32    /// Route fond in proactive mode
   17.33    struct ProactiveRoute
   17.34 @@ -127,7 +133,7 @@
   17.35      uint32_t metric;
   17.36      Time whenExpire;
   17.37      uint32_t seqnum;
   17.38 -    std::vector<std::pair<uint32_t, Mac48Address> > precursors;
   17.39 +    std::vector<Precursor> precursors;
   17.40    };
   17.41  
   17.42    /// List of routes
    18.1 --- a/src/devices/mesh/dot11s/ie-dot11s-prep.cc	Mon Nov 09 13:32:18 2009 -0500
    18.2 +++ b/src/devices/mesh/dot11s/ie-dot11s-prep.cc	Mon Nov 09 13:36:23 2009 -0500
    18.3 @@ -135,6 +135,7 @@
    18.4  IePrep::DecrementTtl ()
    18.5  {
    18.6    m_ttl--;
    18.7 +  m_hopcount ++;
    18.8  }
    18.9  
   18.10  void
    19.1 --- a/src/devices/mesh/dot11s/ie-dot11s-preq.cc	Mon Nov 09 13:32:18 2009 -0500
    19.2 +++ b/src/devices/mesh/dot11s/ie-dot11s-preq.cc	Mon Nov 09 13:36:23 2009 -0500
    19.3 @@ -317,17 +317,17 @@
    19.4  IePreq::Print (std::ostream &os) const
    19.5  {
    19.6    os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
    19.7 -  os << " originator address  = " << m_originatorAddress << "std::endl";
    19.8 -  os << " TTL                 = " << (uint16_t) m_ttl << "std::endl";
    19.9 -  os << " hop count           = " << (uint16_t) m_hopCount << "std::endl";
   19.10 -  os << " metric              = " << m_metric << "std::endl";
   19.11 -  os << " seqno               = " << m_originatorSeqNumber << "std::endl";
   19.12 -  os << " lifetime            = " << m_lifetime << "std::endl";
   19.13 -  os << " preq ID             = " << m_preqId << "std::endl";
   19.14 -  os << " Destinations are:std::endl";
   19.15 +  os << " originator address  = " << m_originatorAddress << std::endl;
   19.16 +  os << " TTL                 = " << (uint16_t) m_ttl << std::endl;
   19.17 +  os << " hop count           = " << (uint16_t) m_hopCount << std::endl;
   19.18 +  os << " metric              = " << m_metric << std::endl;
   19.19 +  os << " seqno               = " << m_originatorSeqNumber << std::endl;
   19.20 +  os << " lifetime            = " << m_lifetime << std::endl;
   19.21 +  os << " preq ID             = " << m_preqId << std::endl;
   19.22 +  os << " Destinations are:" << std::endl;
   19.23    for (int j = 0; j < m_destCount; j++)
   19.24      {
   19.25 -      os << "    " << m_destinations[j]->GetDestinationAddress () << "std::endl";
   19.26 +      os << "    " << m_destinations[j]->GetDestinationAddress () << std::endl;
   19.27      }
   19.28    os << "</information_element>" << std::endl;
   19.29  }
    20.1 --- a/src/devices/mesh/dot11s/ie-dot11s-rann.cc	Mon Nov 09 13:32:18 2009 -0500
    20.2 +++ b/src/devices/mesh/dot11s/ie-dot11s-rann.cc	Mon Nov 09 13:36:23 2009 -0500
    20.3 @@ -152,12 +152,12 @@
    20.4  IeRann::Print (std::ostream &os) const
    20.5  {
    20.6    os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
    20.7 -  os << "  flags              = " << (int) m_flags << "std::endl";
    20.8 -  os << "  hop count          = " << (int) m_hopcount << "std::endl";
    20.9 -  os << "  TTL                = " << (int) m_ttl << "std::endl";
   20.10 -  os << "  originator address = " << m_originatorAddress << "std::endl";
   20.11 -  os << "  dst seq. number    = " << m_destSeqNumber << "std::endl";
   20.12 -  os << "  metric             = " << m_metric << "std::endl";
   20.13 +  os << "  flags              = " << (int) m_flags << std::endl;
   20.14 +  os << "  hop count          = " << (int) m_hopcount << std::endl;
   20.15 +  os << "  TTL                = " << (int) m_ttl << std::endl;
   20.16 +  os << "  originator address = " << m_originatorAddress << std::endl;
   20.17 +  os << "  dst seq. number    = " << m_destSeqNumber << std::endl;
   20.18 +  os << "  metric             = " << m_metric << std::endl;
   20.19    os << "</information_element>" << std::endl;
   20.20  }
   20.21  
    21.1 --- a/src/internet-stack/ipv4-l3-protocol.cc	Mon Nov 09 13:32:18 2009 -0500
    21.2 +++ b/src/internet-stack/ipv4-l3-protocol.cc	Mon Nov 09 13:36:23 2009 -0500
    21.3 @@ -82,8 +82,7 @@
    21.4  }
    21.5  
    21.6  Ipv4L3Protocol::Ipv4L3Protocol()
    21.7 -  : m_nInterfaces (0),
    21.8 -    m_identification (0)
    21.9 +  : m_identification (0)
   21.10  {
   21.11    NS_LOG_FUNCTION_NOARGS ();
   21.12  }
   21.13 @@ -266,9 +265,8 @@
   21.14  Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
   21.15  {
   21.16    NS_LOG_FUNCTION (this << interface);
   21.17 -  uint32_t index = m_nInterfaces;
   21.18 +  uint32_t index = m_interfaces.size ();
   21.19    m_interfaces.push_back (interface);
   21.20 -  m_nInterfaces++;
   21.21    return index;
   21.22  }
   21.23  
   21.24 @@ -276,14 +274,9 @@
   21.25  Ipv4L3Protocol::GetInterface (uint32_t index) const
   21.26  {
   21.27    NS_LOG_FUNCTION (this << index);
   21.28 -  uint32_t tmp = 0;
   21.29 -  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
   21.30 +  if (index < m_interfaces.size ())
   21.31      {
   21.32 -      if (index == tmp) 
   21.33 -	{
   21.34 -	  return *i;
   21.35 -	}
   21.36 -      tmp++;
   21.37 +      return m_interfaces[index];
   21.38      }
   21.39    return 0;
   21.40  }
   21.41 @@ -292,7 +285,7 @@
   21.42  Ipv4L3Protocol::GetNInterfaces (void) const
   21.43  {
   21.44    NS_LOG_FUNCTION_NOARGS ();
   21.45 -  return m_nInterfaces;
   21.46 +  return m_interfaces.size ();
   21.47  }
   21.48  
   21.49  int32_t 
    22.1 --- a/src/internet-stack/ipv4-l3-protocol.h	Mon Nov 09 13:32:18 2009 -0500
    22.2 +++ b/src/internet-stack/ipv4-l3-protocol.h	Mon Nov 09 13:36:23 2009 -0500
    22.3 @@ -22,6 +22,7 @@
    22.4  #define IPV4_L3_PROTOCOL_H
    22.5  
    22.6  #include <list>
    22.7 +#include <vector>
    22.8  #include <stdint.h>
    22.9  #include "ns3/ipv4-address.h"
   22.10  #include "ns3/ptr.h"
   22.11 @@ -233,7 +234,7 @@
   22.12    Ptr<Icmpv4L4Protocol> GetIcmp (void) const;
   22.13    bool IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const;
   22.14  
   22.15 -  typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
   22.16 +  typedef std::vector<Ptr<Ipv4Interface> > Ipv4InterfaceList;
   22.17    typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
   22.18    typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
   22.19  
    23.1 --- a/test.py	Mon Nov 09 13:32:18 2009 -0500
    23.2 +++ b/test.py	Mon Nov 09 13:36:23 2009 -0500
    23.3 @@ -132,6 +132,7 @@
    23.4      ("tutorial/second", "True", "True"),
    23.5      ("tutorial/third", "True", "True"),
    23.6      ("tutorial/fourth", "True", "True"),
    23.7 +    ("tutorial/fifth", "True", "True"),
    23.8  
    23.9      ("udp/udp-echo", "True", "True"),
   23.10  
   23.11 @@ -616,6 +617,7 @@
   23.12          self.shell_command = ""
   23.13          self.display_name = ""
   23.14          self.basedir = ""
   23.15 +        self.tempdir = ""
   23.16          self.cwd = ""
   23.17          self.tmp_file_name = ""
   23.18          self.returncode = False
   23.19 @@ -674,6 +676,13 @@
   23.20          self.basedir = basedir
   23.21  
   23.22      #
   23.23 +    # This is the directory to which a running test suite should write any 
   23.24 +    # temporary files.
   23.25 +    #
   23.26 +    def set_tempdir(self, tempdir):
   23.27 +        self.tempdir = tempdir
   23.28 +
   23.29 +    #
   23.30      # This is the current working directory that will be given to an executing
   23.31      # test as it is being run.  It will be used for examples to tell them where
   23.32      # to write all of the pcap files that we will be carefully ignoring.  For
   23.33 @@ -766,7 +775,8 @@
   23.34                      # file name
   23.35                      #
   23.36                      (job.returncode, standard_out, standard_err, et) = run_job_synchronously(job.shell_command + 
   23.37 -                        " --basedir=%s --out=%s" % (job.basedir, job.tmp_file_name), job.cwd, options.valgrind)
   23.38 +                        " --basedir=%s --tempdir=%s --out=%s" % (job.basedir, job.tempdir, job.tmp_file_name), 
   23.39 +                        job.cwd, options.valgrind)
   23.40  
   23.41                  job.set_elapsed_time(et)
   23.42  
   23.43 @@ -1004,6 +1014,7 @@
   23.44              job.set_tmp_file_name(os.path.join(testpy_output_dir, "%s.xml" % test))
   23.45              job.set_cwd(os.getcwd())
   23.46              job.set_basedir(os.getcwd())
   23.47 +            job.set_tempdir(testpy_output_dir)
   23.48              if (options.multiple):
   23.49                  multiple = " --multiple"
   23.50              else:
   23.51 @@ -1074,6 +1085,7 @@
   23.52                          job.set_tmp_file_name("")
   23.53                          job.set_cwd(testpy_output_dir)
   23.54                          job.set_basedir(os.getcwd())
   23.55 +                        job.set_tempdir(testpy_output_dir)
   23.56                          job.set_shell_command("examples/%s" % test)
   23.57  
   23.58                          if options.valgrind and not eval(do_valgrind_run):
   23.59 @@ -1097,6 +1109,7 @@
   23.60          job.set_tmp_file_name("")
   23.61          job.set_cwd(testpy_output_dir)
   23.62          job.set_basedir(os.getcwd())
   23.63 +        job.set_tempdir(testpy_output_dir)
   23.64          job.set_shell_command("examples/%s" % options.example)
   23.65          
   23.66          if options.verbose:
    24.1 --- a/utils/test-runner.cc	Mon Nov 09 13:32:18 2009 -0500
    24.2 +++ b/utils/test-runner.cc	Mon Nov 09 13:36:23 2009 -0500
    24.3 @@ -40,11 +40,13 @@
    24.4    bool doKinds = false;
    24.5  
    24.6    bool haveBasedir = false;
    24.7 +  bool haveTempdir = false;
    24.8    bool haveOutfile = false;
    24.9    bool haveType = false;
   24.10  
   24.11    std::string suiteName;
   24.12    std::string basedir;
   24.13 +  std::string tempdir;
   24.14    std::string outfileName;
   24.15    std::string typeName;
   24.16  
   24.17 @@ -96,6 +98,12 @@
   24.18            doSuite = true;
   24.19          }
   24.20  
   24.21 +      if (arg.find ("--tempdir=") != std::string::npos)
   24.22 +        {
   24.23 +          tempdir = arg.substr (arg.find_first_of ("=") + 1, 9999);
   24.24 +          haveTempdir = true;
   24.25 +        }
   24.26 +
   24.27        if (arg.compare ("--verbose") == 0)
   24.28          {
   24.29            doVerbose = true;
   24.30 @@ -247,6 +255,7 @@
   24.31        if (doSuite == false || (doSuite == true && suiteName == testSuite->GetName ()))
   24.32          {
   24.33            testSuite->SetBaseDir (basedir);
   24.34 +          testSuite->SetTempDir (tempdir);
   24.35            testSuite->SetStream (pofs);
   24.36            testSuite->SetVerbose (doVerbose);
   24.37            testSuite->SetContinueOnFailure (doMultiple);