--- a/bindings/python/ns3modulegen.py Tue Jan 13 17:17:37 2009 -0500
+++ b/bindings/python/ns3modulegen.py Tue Jan 20 11:41:57 2009 -0500
@@ -137,7 +137,7 @@
root_module.classes.remove(root_module['ns3::%s' % clsname])
if 'RealTime' not in enabled_features:
- for clsname in ['WallClockSynchronizer', 'RealtimeSimulatorImpl', 'RealtimeEventLock']:
+ for clsname in ['WallClockSynchronizer', 'RealtimeSimulatorImpl']:
root_module.classes.remove(root_module['ns3::%s' % clsname])
root_module.enums.remove(root_module['ns3::RealtimeSimulatorImpl::SynchronizationMode'])
@@ -146,5 +146,14 @@
out.close()
if __name__ == '__main__':
- main()
+ if 0:
+ try:
+ import cProfile as profile
+ except ImportError:
+ main()
+ else:
+ print >> sys.stderr, "** running under profiler"
+ profile.run('main()', 'ns3modulegen.pstat')
+ else:
+ main()
--- a/bindings/python/wscript Tue Jan 13 17:17:37 2009 -0500
+++ b/bindings/python/wscript Tue Jan 20 11:41:57 2009 -0500
@@ -14,11 +14,6 @@
import Build
import Utils
-## Adjust python path to look for our local copy of pybindgen
-LOCAL_PYBINDGEN_PATH = os.path.join(os.getcwd(), "bindings", "python", "pybindgen")
-#PYBINDGEN_BRANCH = 'lp:pybindgen'
-PYBINDGEN_BRANCH = 'https://launchpad.net/pybindgen'
-
## https://launchpad.net/pybindgen/
REQUIRED_PYBINDGEN_VERSION = (0, 9, 0, 605)
REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
@@ -33,8 +28,6 @@
def set_pybindgen_pythonpath(env):
if env['WITH_PYBINDGEN']:
add_to_python_path(env['WITH_PYBINDGEN'])
- else:
- add_to_python_path(LOCAL_PYBINDGEN_PATH)
def set_options(opt):
@@ -47,67 +40,11 @@
help=("Rescan Python bindings. Needs working GCCXML / pygccxml environment."),
action="store_true", default=False,
dest='python_scan')
- opt.add_option('--pybindgen-checkout',
- help=("During configure, force checkout of pybingen inside ns-3, "
- "instead of using the system installed version."),
- action="store_true", default=False,
- dest='pybindgen_checkout')
opt.add_option('--with-pybindgen',
help=('Path to an existing pybindgen source tree to use.'),
default=None,
dest='with_pybindgen', type="string")
-def fetch_pybindgen(conf):
- """
- Fetches pybindgen from launchpad as bindings/python/pybindgen.
- Returns True if successful, False it not.
- """
- bzr = conf.find_program("bzr")
- if not bzr:
- Logs.warn("the program 'bzr' is needed in order to fetch pybindgen")
- return False
- if len(REQUIRED_PYBINDGEN_VERSION) == 4:
- rev = "-rrevno:%i" % REQUIRED_PYBINDGEN_VERSION[3]
- else:
- rev = "-rtag:%s" % '.'.join([str(x) for x in REQUIRED_PYBINDGEN_VERSION])
-
- if os.path.exists(LOCAL_PYBINDGEN_PATH):
- print "Trying to update pybindgen; this will fail if no network connection is available. Hit Ctrl-C to skip."
-
- cmd = [bzr, "pull", rev, PYBINDGEN_BRANCH]
- print " => ", ' '.join(cmd)
- try:
- if subprocess.Popen(cmd, cwd=LOCAL_PYBINDGEN_PATH).wait():
- return False
- except KeyboardInterrupt:
- print "Interrupted; Python bindings will be disabled."
- return False
- print "Update was successful."
- else:
- print "Trying to fetch pybindgen; this will fail if no network connection is available. Hit Ctrl-C to skip."
- cmd = [bzr, "checkout", rev, PYBINDGEN_BRANCH, LOCAL_PYBINDGEN_PATH]
- print " => ", ' '.join(cmd)
- try:
- if subprocess.Popen(cmd).wait():
- return False
- except KeyboardInterrupt:
- print "Interrupted; Python bindings will be disabled."
- shutil.rmtree(LOCAL_PYBINDGEN_PATH, True)
- return False
- print "Fetch was successful."
-
- ## generate a fake version.py file in pybindgen it's safer this
- ## way, since the normal version generation process requires
- ## bazaar python bindings, which may not be available.
- vfile = open(os.path.join(LOCAL_PYBINDGEN_PATH, "pybindgen", "version.py"), "wt")
- vfile.write("""
-# (fake version generated by ns-3)
-__version__ = %r
-""" % list(REQUIRED_PYBINDGEN_VERSION))
- vfile.close()
-
- return True
-
def configure(conf):
conf.env['ENABLE_PYTHON_BINDINGS'] = False
@@ -140,9 +77,6 @@
conf.env['WITH_PYBINDGEN'] = os.path.abspath(Options.options.with_pybindgen)
no_net = True
- if Options.options.pybindgen_checkout:
- fetch_pybindgen(conf)
-
set_pybindgen_pythonpath(conf.env)
try:
@@ -484,7 +418,8 @@
bindgen = bld.new_task_gen('command', source=source, target=target,
command=argv, variables=dict(FEATURES=(','.join(features))))
-
+ bindgen.before = 'cxx'
+ bindgen.after = 'gen_everything_h_task'
## we build python bindings if either we have the tools to
## generate them or if the pregenerated source file is already
@@ -499,7 +434,15 @@
pymod.target = 'ns3/_ns3'
pymod.name = 'ns3module'
pymod.uselib_local = "ns3"
- pymod.env.append_value('CXXDEFINES', ['NS_DEPRECATED=', 'NS3_DEPRECATED_H'])
+
+ defines = list(pymod.env['CXXDEFINES'])
+ defines.extend(['NS_DEPRECATED=', 'NS3_DEPRECATED_H'])
+ if Options.platform == 'win32':
+ try:
+ defines.remove('_DEBUG') # causes undefined symbols on win32
+ except ValueError:
+ pass
+ pymod.env['CXXDEFINES'] = defines
# copy the __init__.py file to the build dir. waf can't handle
# this, it's against waf's principles to have build dir files
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wifi-ap.py Tue Jan 20 11:41:57 2009 -0500
@@ -0,0 +1,166 @@
+# -*- Mode: Python; -*-
+# /*
+# * Copyright (c) 2005,2006,2007 INRIA
+# * Copyright (c) 2009 INESC Porto
+# *
+# * This program is free software; you can redistribute it and/or modify
+# * it under the terms of the GNU General Public License version 2 as
+# * published by the Free Software Foundation;
+# *
+# * This program is distributed in the hope that it will be useful,
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# * GNU General Public License for more details.
+# *
+# * You should have received a copy of the GNU General Public License
+# * along with this program; if not, write to the Free Software
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# *
+# * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+# * Gustavo Carneiro <gjc@inescporto.pt>
+# */
+
+import sys
+import ns3
+
+# void
+# DevTxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+# {
+# std::cout << " TX to=" << address << " p: " << *p << std::endl;
+# }
+# void
+# DevRxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+# {
+# std::cout << " RX from=" << address << " p: " << *p << std::endl;
+# }
+# void
+# PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
+# {
+# std::cout << "PHYRXOK mode=" << mode << " snr=" << snr << " " << *packet << std::endl;
+# }
+# void
+# PhyRxErrorTrace (std::string context, Ptr<const Packet> packet, double snr)
+# {
+# std::cout << "PHYRXERROR snr=" << snr << " " << *packet << std::endl;
+# }
+# void
+# PhyTxTrace (std::string context, Ptr<const Packet> packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower)
+# {
+# std::cout << "PHYTX mode=" << mode << " " << *packet << std::endl;
+# }
+# void
+# PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::State state)
+# {
+# std::cout << " state=";
+# switch (state) {
+# case WifiPhy::TX:
+# std::cout << "tx ";
+# break;
+# case WifiPhy::SYNC:
+# std::cout << "sync ";
+# break;
+# case WifiPhy::CCA_BUSY:
+# std::cout << "cca-busy";
+# break;
+# case WifiPhy::IDLE:
+# std::cout << "idle ";
+# break;
+# }
+# std::cout << " start="<<start<<" duration="<<duration<<std::endl;
+# }
+
+def SetPosition(node, position):
+ mobility = node.GetObject(ns3.MobilityModel.GetTypeId())
+ mobility.SetPosition(position)
+
+
+def GetPosition(node):
+ mobility = node.GetObject(ns3.MobilityModel.GetTypeId())
+ return mobility.GetPosition()
+
+def AdvancePosition(node):
+ pos = GetPosition (node);
+ pos.x += 5.0
+ if pos.x >= 210.0:
+ return
+ SetPosition(node, pos)
+ ns3.Simulator.Schedule(ns3.Seconds(1.0), AdvancePosition, node)
+
+
+def main(argv):
+ ns3.Packet.EnablePrinting ();
+
+ # enable rts cts all the time.
+ ns3.Config.SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", ns3.StringValue("0"))
+ # disable fragmentation
+ ns3.Config.SetDefault("ns3::WifiRemoteStationManager::FragmentationThreshold", ns3.StringValue ("2200"))
+
+ wifi = ns3.WifiHelper.Default()
+ mobility = ns3.MobilityHelper()
+ stas = ns3.NodeContainer()
+ ap = ns3.NodeContainer()
+ #NetDeviceContainer staDevs;
+ packetSocket = ns3.PacketSocketHelper()
+
+ stas.Create(2)
+ ap.Create(1)
+
+ # give packet socket powers to nodes.
+ packetSocket.Install(stas)
+ packetSocket.Install(ap)
+
+ wifiPhy = ns3.YansWifiPhyHelper.Default()
+ wifiChannel = ns3.YansWifiChannelHelper.Default()
+ wifiPhy.SetChannel(wifiChannel.Create())
+
+ ssid = ns3.Ssid("wifi-default")
+ wifi.SetRemoteStationManager("ns3::ArfWifiManager")
+ # setup stas.
+ wifi.SetMac("ns3::NqstaWifiMac",
+ "Ssid", ns3.SsidValue(ssid),
+ "ActiveProbing", ns3.BooleanValue(False))
+ staDevs = wifi.Install(wifiPhy, stas)
+ # setup ap.
+ wifi.SetMac("ns3::NqapWifiMac", "Ssid", ns3.SsidValue(ssid),
+ "BeaconGeneration", ns3.BooleanValue(True),
+ "BeaconInterval", ns3.TimeValue(ns3.Seconds(2.5)))
+ wifi.Install(wifiPhy, ap)
+
+ # mobility.
+ mobility.Install(stas)
+ mobility.Install(ap)
+
+ ns3.Simulator.Schedule(ns3.Seconds(1.0), AdvancePosition, ap.Get(0))
+
+ socket = ns3.PacketSocketAddress()
+ socket.SetSingleDevice(staDevs.Get(0).GetIfIndex())
+ socket.SetPhysicalAddress(staDevs.Get(1).GetAddress())
+ socket.SetProtocol(1)
+
+ onoff = ns3.OnOffHelper("ns3::PacketSocketFactory", ns3.Address(socket))
+ onoff.SetAttribute("OnTime", ns3.RandomVariableValue(ns3.ConstantVariable(42)))
+ onoff.SetAttribute("OffTime", ns3.RandomVariableValue(ns3.ConstantVariable(0)))
+
+ apps = onoff.Install(ns3.NodeContainer(stas.Get(0)))
+ apps.Start(ns3.Seconds(0.5))
+ apps.Stop(ns3.Seconds(43.0))
+
+ ns3.Simulator.Stop(ns3.Seconds(44.0))
+
+ # Config::Connect ("/NodeList/*/DeviceList/*/Tx", MakeCallback (&DevTxTrace));
+ # Config::Connect ("/NodeList/*/DeviceList/*/Rx", MakeCallback (&DevRxTrace));
+ # Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxOk", MakeCallback (&PhyRxOkTrace));
+ # Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxError", MakeCallback (&PhyRxErrorTrace));
+ # Config::Connect ("/NodeList/*/DeviceList/*/Phy/Tx", MakeCallback (&PhyTxTrace));
+ # Config::Connect ("/NodeList/*/DeviceList/*/Phy/State", MakeCallback (&PhyStateTrace));
+
+ ns3.Simulator.Run()
+
+ ns3.Simulator.Destroy()
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
+
--- a/regression.py Tue Jan 13 17:17:37 2009 -0500
+++ b/regression.py Tue Jan 20 11:41:57 2009 -0500
@@ -14,32 +14,6 @@
import wutils
-#
-# The directory in which the tarball of the reference traces lives. This is
-# used if Mercurial is not on the system.
-#
-REGRESSION_TRACES_URL = "http://www.nsnam.org/releases/"
-
-#
-# The path to the Mercurial repository used to find the reference traces if
-# we find "hg" on the system. We expect that the repository will be named
-# identically to refDirName below
-#
-REGRESSION_TRACES_REPO = "http://code.nsnam.org/"
-
-#
-# Name of the local directory where the regression code lives.
-#
-REGRESSION_DIR = "regression"
-
-#
-# The last part of the path name to use to find the regression traces. The
-# path will be APPNAME + '-' + VERSION + REGRESSION_SUFFIX, e.g.,
-# ns-3-dev-ref-traces
-#
-REGRESSION_SUFFIX = "-ref-traces"
-
-
def dev_null():
if sys.platform == 'win32':
return open("NUL:", "w")
@@ -90,19 +64,13 @@
os.mkdir(refTestDirName)
if pyscript is None:
- Options.options.cwd_launch = refTestDirName
tmpl = "%s"
for arg in arguments:
tmpl = tmpl + " " + arg
- wutils.run_program(testName, tmpl)
+ wutils.run_program(testName, tmpl, cwd=refTestDirName)
else:
argv = [self.env['PYTHON'], os.path.join(Options.cwd_launch, *os.path.split(pyscript))] + arguments
- before = os.getcwd()
- os.chdir(refTestDirName)
- try:
- wutils.run_argv(argv)
- finally:
- os.chdir(before)
+ wutils.run_argv(argv, cwd=refTestDirName)
print "Remember to commit " + refTestDirName
return 0
else:
@@ -110,12 +78,11 @@
print "Cannot locate reference traces in " + refTestDirName
return 1
-
if refTestName is None:
traceDirName = testName + ".ref"
else:
traceDirName = refTestName
- traceDirName = os.path.join ('traces', traceDirName)
+ traceDirName = os.path.join('regression', 'traces', traceDirName)
try:
shutil.rmtree(traceDirName)
@@ -123,20 +90,13 @@
pass
os.mkdir(traceDirName)
- #os.system("./waf --cwd regression/traces --run " +
- # testName + " > /dev/null 2>&1")
-
if pyscript is None:
- Options.options.cwd_launch = traceDirName
- wutils.run_program(testName, command_template=wutils.get_command_template(*arguments))
+ wutils.run_program(testName,
+ command_template=wutils.get_command_template(*arguments),
+ cwd=traceDirName)
else:
argv = [self.env['PYTHON'], os.path.join('..', '..', '..', *os.path.split(pyscript))] + arguments
- before = os.getcwd()
- os.chdir(traceDirName)
- try:
- wutils.run_argv(argv)
- finally:
- os.chdir(before)
+ wutils.run_argv(argv, cwd=traceDirName)
if verbose:
#diffCmd = "diff traces " + refTestDirName + " | head"
@@ -179,22 +139,15 @@
def run_regression(reference_traces):
"""Execute regression tests. Called with cwd set to the 'regression' subdir of ns-3.
- @param reference_traces: reference traces directory, or None for default.
+ @param reference_traces: reference traces directory.
"""
- testdir = "tests"
+ testdir = os.path.join("regression", "tests")
if not os.path.exists(testdir):
print "Tests directory does not exist"
sys.exit(3)
- dir_name = (wutils.APPNAME + '-' + wutils.VERSION + REGRESSION_SUFFIX)
- if reference_traces is None:
- reference_traces = dir_name
- no_net = False
- else:
- no_net = True
-
sys.path.append(testdir)
sys.modules['tracediff'] = Regression(testdir, reference_traces)
@@ -205,32 +158,6 @@
print "========== Running Regression Tests =========="
env = Build.bld.env
- if not no_net:
- if env['MERCURIAL']:
- print "Synchronizing reference traces using Mercurial."
- if not os.path.exists(reference_traces):
- print "Cloning " + REGRESSION_TRACES_REPO + dir_name + " from repo."
- argv = ["hg", "clone", REGRESSION_TRACES_REPO + dir_name, reference_traces]
- rv = subprocess.Popen(argv).wait()
- else:
- _dir = os.getcwd()
- os.chdir(reference_traces)
- try:
- print "Pulling " + REGRESSION_TRACES_REPO + dir_name + " from repo."
- result = subprocess.Popen(["hg", "-q", "pull", REGRESSION_TRACES_REPO + dir_name]).wait()
- if not result:
- result = subprocess.Popen(["hg", "-q", "update"]).wait()
- finally:
- os.chdir("..")
- if result:
- raise Utils.WafError("Synchronizing reference traces using Mercurial failed.")
- else:
- if not os.path.exists(reference_traces):
- traceball = dir_name + wutils.TRACEBALL_SUFFIX
- print "Retrieving " + traceball + " from web."
- urllib.urlretrieve(REGRESSION_TRACES_URL + traceball, traceball)
- os.system("tar -xjf %s -C .." % (traceball))
- print "Done."
if not os.path.exists(reference_traces):
print "Reference traces directory (%s) does not exist" % reference_traces
@@ -252,7 +179,7 @@
except NotImplementedError:
print "SKIP " + test
- return len(bad) > 0
+ return (len(bad) > 0)
def _run_regression_test(test):
@@ -261,15 +188,15 @@
Arguments:
test -- the name of the test
"""
-
- if os.path.exists("traces"):
- files = os.listdir("traces")
+ traces_dir = os.path.join("regression", "traces")
+ if os.path.exists(traces_dir):
+ files = os.listdir(traces_dir)
for file in files:
if file == '.' or file == '..':
continue
shutil.rmtree(os.path.join("traces", file), ignore_errors=True)
else:
- os.mkdir("traces")
+ os.mkdir(traces_dir)
mod = __import__(test, globals(), locals(), [])
return mod.run(verbose=(Options.options.verbose > 0),
--- a/samples/wscript Tue Jan 13 17:17:37 2009 -0500
+++ b/samples/wscript Tue Jan 20 11:41:57 2009 -0500
@@ -19,8 +19,9 @@
obj = bld.create_ns3_program('main-test')
obj.source = 'main-test.cc'
- obj = bld.create_ns3_program('main-test-sync')
- obj.source = 'main-test-sync.cc'
+ if bld.env['ENABLE_THREADING']:
+ obj = bld.create_ns3_program('main-test-sync')
+ obj.source = 'main-test-sync.cc'
obj = bld.create_ns3_program('main-simple',
['node', 'internet-stack', 'onoff'])
--- a/src/common/pcap-writer.cc Tue Jan 13 17:17:37 2009 -0500
+++ b/src/common/pcap-writer.cc Tue Jan 20 11:41:57 2009 -0500
@@ -86,7 +86,7 @@
NS_LOG_LOGIC ("Created writer " << m_writer);
- m_writer->open (name.c_str ());
+ m_writer->open (name.c_str (), std::ios_base::binary | std::ios_base::out);
NS_ABORT_MSG_IF (m_writer->fail (), "PcapWriter::Open(): m_writer->open(" << name.c_str () << ") failed");
NS_ASSERT_MSG (m_writer->is_open (), "PcapWriter::Open(): m_writer not open");
--- a/src/devices/wifi/wifi-mac-queue.cc Tue Jan 13 17:17:37 2009 -0500
+++ b/src/devices/wifi/wifi-mac-queue.cc Tue Jan 20 11:41:57 2009 -0500
@@ -28,6 +28,9 @@
namespace ns3 {
+NS_OBJECT_ENSURE_REGISTERED (WifiMacQueue);
+
+
WifiMacQueue::Item::Item (Ptr<const Packet> packet,
WifiMacHeader const &hdr,
Time tstamp)
@@ -37,7 +40,7 @@
TypeId
WifiMacQueue::GetTypeId (void)
{
- static TypeId tid = TypeId ("WifiMacQueue")
+ static TypeId tid = TypeId ("ns3::WifiMacQueue")
.SetParent<Object> ()
.AddConstructor<WifiMacQueue> ()
.AddAttribute ("MaxPacketNumber", "If a packet arrives when there are already this number of packets, it is dropped.",
--- a/src/simulator/calendar-scheduler.cc Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/calendar-scheduler.cc Tue Jan 20 11:41:57 2009 -0500
@@ -331,6 +331,7 @@
DoInsert (*j);
}
}
+ delete [] oldBuckets;
}
void
CalendarScheduler::Resize (uint32_t newSize)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/ns2-calendar-scheduler.cc Tue Jan 20 11:41:57 2009 -0500
@@ -0,0 +1,495 @@
+/* -*- Mode:C++; c-basic-offset:8; tab-width:8; -*- */
+/*
+ * Copyright (c) 1997 David Wetherall
+ * Copyright (c) 2005 David Wei
+ * Copyright (c) 2009 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ns2-calendar-scheduler.h"
+#include "event-impl.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include <cassert>
+#include <math.h>
+#include <string.h>
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("Ns2CalendarScheduler");
+
+NS_OBJECT_ENSURE_REGISTERED (Ns2CalendarScheduler);
+
+#define CALENDAR_HASH(key) ((key.m_ts / width_) % nbuckets_)
+
+TypeId
+Ns2CalendarScheduler::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ns2CalendarScheduler")
+ .SetParent<Scheduler> ()
+ .AddConstructor<Ns2CalendarScheduler> ()
+ ;
+ return tid;
+}
+
+Ns2CalendarScheduler::Ns2CalendarScheduler ()
+{
+ NS_LOG_FUNCTION (this);
+
+ adjust_new_width_interval_ = 10;
+ min_bin_width_ = 1;
+ avg_gap_ = -2;
+ last_time_ = 0;
+ gap_num_ = 0;
+ head_search_ = 0;
+ insert_search_ = 0;
+ round_num_ = 0;
+ time_to_newwidth_ = adjust_new_width_interval_;
+ cal_clock_ = Scheduler::EventKey ();
+ reinit(4, 1, cal_clock_);
+}
+Ns2CalendarScheduler::~Ns2CalendarScheduler ()
+{
+ NS_LOG_FUNCTION (this);
+
+ for (int i = 0; i < nbuckets_; i++) {
+ Bucket *bucket = &buckets_[i];
+ if (bucket->list_ == 0) {
+ continue;
+ }
+ if (bucket->list_->next_ == bucket->list_) {
+ delete bucket->list_;
+ continue;
+ }
+ BucketItem *next;
+ BucketItem *cur;
+ for (cur = bucket->list_;
+ cur->next_ != bucket->list_;
+ cur = next) {
+ next = cur->next_;
+ delete cur;
+ }
+ delete cur;
+ }
+ delete [] buckets_;
+ qsize_ = 0;
+ stat_qsize_ = 0;
+}
+void
+Ns2CalendarScheduler::Insert (const Event &event)
+{
+ NS_LOG_FUNCTION (this);
+
+ Scheduler::EventKey newtime = event.key;
+ int i = CALENDAR_HASH(newtime);
+
+ Bucket* current=(&buckets_[i]);
+ BucketItem *head = current->list_;
+ BucketItem *after=0;
+ BucketItem *e = new BucketItem ();
+ e->event = event;
+
+ if (!head) {
+ current->list_ = e;
+ e->next_ = e->prev_ = e;
+ ++stat_qsize_;
+ ++(current->count_);
+ } else {
+ insert_search_++;
+ if (newtime < head->event.key) {
+ // e-> head -> ...
+ e->next_ = head;
+ e->prev_ = head->prev_;
+ e->prev_->next_ = e;
+ head->prev_ = e;
+ current->list_ = e;
+ ++stat_qsize_;
+ ++(current->count_);
+ } else {
+ for (after = head->prev_; newtime < after->event.key; after = after->prev_)
+ { insert_search_++; };
+ //...-> after -> e -> ...
+ e->next_ = after->next_;
+ e->prev_ = after;
+ e->next_->prev_ = e;
+ after->next_ = e;
+ if (after->event.key < newtime) {
+ //unique timing
+ ++stat_qsize_;
+ ++(current->count_);
+ }
+ }
+ }
+ ++qsize_;
+ //assert(e == buckets_[i].list_ || e->prev_->time_ <= e->time_);
+ //assert(e == buckets_[i].list_->prev_ || e->next_->time_ >= e->time_);
+
+ if (stat_qsize_ > top_threshold_) {
+ resize(nbuckets_ << 1, cal_clock_);
+ return;
+ }
+}
+bool
+Ns2CalendarScheduler::IsEmpty (void) const
+{
+ return qsize_ == 0;
+}
+Scheduler::Event
+Ns2CalendarScheduler::PeekNext (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (!IsEmpty ());
+
+ BucketItem *e = const_cast<Ns2CalendarScheduler *> (this)->head ();
+ NS_ASSERT (e != 0);
+
+ return e->event;
+}
+
+
+Scheduler::Event
+Ns2CalendarScheduler::RemoveNext (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (!IsEmpty ());
+
+ BucketItem *e = head ();
+ NS_ASSERT (e != 0);
+
+ if (last_time_ == 0) last_time_ = e->event.key.m_ts;
+ else
+ {
+ gap_num_ ++;
+ if (gap_num_ >= qsize_ ) {
+ uint64_t tt_gap_ = e->event.key.m_ts - last_time_;
+ avg_gap_ = tt_gap_ / gap_num_;
+ gap_num_ = 0;
+ last_time_ = e->event.key.m_ts;
+ round_num_ ++;
+ if ((round_num_ > 20) &&
+ (( head_search_> (insert_search_<<1))
+ ||( insert_search_> (head_search_<<1)) ))
+ {
+ resize(nbuckets_, cal_clock_);
+ round_num_ = 0;
+ } else {
+ if (round_num_ > 100) {
+ round_num_ = 0;
+ head_search_ = 0;
+ insert_search_ = 0;
+ }
+ }
+ }
+ }
+
+ int l = lastbucket_;
+
+ // update stats and unlink
+ if (e->next_ == e || e->next_->event.key != e->event.key) {
+ --stat_qsize_;
+ //assert(stat_qsize_ >= 0);
+ --buckets_[l].count_;
+ //assert(buckets_[l].count_ >= 0);
+ }
+ --qsize_;
+
+ if (e->next_ == e)
+ buckets_[l].list_ = 0;
+ else {
+ e->next_->prev_ = e->prev_;
+ e->prev_->next_ = e->next_;
+ buckets_[l].list_ = e->next_;
+ }
+
+ e->next_ = e->prev_ = NULL;
+
+
+ //if (buckets_[l].count_ == 0)
+ // assert(buckets_[l].list_ == 0);
+
+ if (stat_qsize_ < bot_threshold_) {
+ resize(nbuckets_ >> 1, cal_clock_);
+ }
+
+ Scheduler::Event event = e->event;
+ delete e;
+ return event;
+}
+
+void
+Ns2CalendarScheduler::Remove (const Event &ev)
+{
+ NS_ASSERT (!IsEmpty ());
+
+
+ int i = CALENDAR_HASH(ev.key);
+
+ Bucket* current=(&buckets_[i]);
+ BucketItem *head = current->list_;
+ BucketItem *e=0;
+
+ if (!head) {
+ NS_LOG_DEBUG ("event not in scheduler");
+ return;
+ }
+ for (e = head->prev_; ev.key != e->event.key; e = e->prev_) {}
+ --stat_qsize_;
+ --buckets_[i].count_;
+ if (e->next_ == e) {
+ assert(buckets_[i].list_ == e);
+ buckets_[i].list_ = 0;
+ } else {
+ e->next_->prev_ = e->prev_;
+ e->prev_->next_ = e->next_;
+ if (buckets_[i].list_ == e)
+ buckets_[i].list_ = e->next_;
+ }
+
+ if (buckets_[i].count_ == 0)
+ assert(buckets_[i].list_ == 0);
+
+ e->next_ = e->prev_ = NULL;
+
+ delete e;
+
+ --qsize_;
+
+ return;
+}
+
+Ns2CalendarScheduler::BucketItem *
+Ns2CalendarScheduler::head (void)
+{
+ NS_ASSERT (!IsEmpty ());
+
+ int l = -1, i = lastbucket_;
+ int lastbucket_dec = (lastbucket_) ? lastbucket_ - 1 : nbuckets_ - 1;
+ uint64_t diff;
+ BucketItem *e, *min_e = NULL;
+#define CAL_DEQUEUE(x) \
+do { \
+ head_search_++; \
+ if ((e = buckets_[i].list_) != NULL) { \
+ diff = e->event.key.m_ts - cal_clock_.m_ts; \
+ if (diff < diff##x##_) { \
+ l = i; \
+ goto found_l; \
+ } \
+ if (min_e == NULL || min_e->event.key > e->event.key) { \
+ min_e = e; \
+ l = i; \
+ } \
+ } \
+ if (++i == nbuckets_) i = 0; \
+} while (0)
+
+ // CAL_DEQUEUE applied successively will find the event to
+ // dequeue (within one year) and keep track of the
+ // minimum-priority event seen so far; the argument controls
+ // the criteria used to decide whether the event should be
+ // considered `within one year'. Importantly, the number of
+ // buckets should not be less than 4.
+ CAL_DEQUEUE(0);
+ CAL_DEQUEUE(1);
+ for (; i != lastbucket_dec; ) {
+ CAL_DEQUEUE(2);
+ }
+ // one last bucket is left unchecked - take the minimum
+ // [could have done CAL_DEQUEUE(3) with diff3_ = bwidth*(nbuck*3/2-1)]
+ e = buckets_[i].list_;
+ if (min_e != NULL &&
+ (e == NULL || min_e->event.key < e->event.key))
+ e = min_e;
+ else {
+ //assert(e);
+ l = i;
+ }
+ found_l:
+ //assert(buckets_[l].count_ >= 0);
+ //assert(buckets_[l].list_ == e);
+
+ /* l is the index of the bucket to dequeue, e is the event */
+ /*
+ * still want to advance lastbucket_ and cal_clock_ to save
+ * time when deque() follows.
+ */
+ assert (l != -1);
+ lastbucket_ = l;
+ cal_clock_ = e->event.key;
+
+ return e;
+}
+
+void
+Ns2CalendarScheduler::reinit(int nbuck, uint64_t bwidth, Scheduler::EventKey start)
+{
+ buckets_ = new Bucket[nbuck];
+
+ memset(buckets_, 0, sizeof(Bucket)*nbuck); //faster than ctor
+
+ width_ = bwidth;
+ nbuckets_ = nbuck;
+ qsize_ = 0;
+ stat_qsize_ = 0;
+
+ lastbucket_ = CALENDAR_HASH(start);
+
+ diff0_ = bwidth*nbuck/2;
+ diff1_ = diff0_ + bwidth;
+ diff2_ = bwidth*nbuck;
+ //diff3_ = bwidth*(nbuck*3/2-1);
+
+ bot_threshold_ = (nbuck >> 1) - 2;
+ top_threshold_ = (nbuck << 1);
+}
+
+void
+Ns2CalendarScheduler::resize(int newsize, Scheduler::EventKey start)
+{
+ uint64_t bwidth;
+ if (newsize == nbuckets_) {
+ /* we resize for bwidth*/
+ if (head_search_) bwidth = head_search_; else bwidth = 1;
+ if (insert_search_) bwidth = bwidth / insert_search_;
+ bwidth = static_cast<uint64_t> (sqrt (bwidth) * width_);
+ if (bwidth < min_bin_width_) {
+ if (time_to_newwidth_>0) {
+ time_to_newwidth_ --;
+ head_search_ = 0;
+ insert_search_ = 0;
+ round_num_ = 0;
+ return; //failed to adjust bwidth
+ } else {
+ // We have many (adjust_new_width_interval_) times failure in adjusting bwidth.
+ // should do a reshuffle with newwidth
+ bwidth = newwidth(newsize);
+ }
+ }
+ //snoopy queue calculation
+ } else {
+ /* we resize for size */
+ bwidth = newwidth(newsize);
+ if (newsize < 4)
+ newsize = 4;
+ }
+
+ Bucket *oldb = buckets_;
+ int oldn = nbuckets_;
+
+ reinit(newsize, bwidth, start);
+
+ // copy events to new buckets
+ int i;
+
+ for (i = 0; i < oldn; ++i) {
+ // we can do inserts faster, if we use insert2, but to
+ // preserve FIFO, we have to start from the end of
+ // each bucket and use insert2
+ if (oldb[i].list_) {
+ BucketItem *tail = oldb[i].list_->prev_;
+ BucketItem *e = tail;
+ do {
+ BucketItem* ep = e->prev_;
+ e->next_ = e->prev_ = 0;
+ insert2(e);
+ e = ep;
+ } while (e != tail);
+ }
+ }
+ head_search_ = 0;
+ insert_search_ = 0;
+ round_num_ = 0;
+ delete [] oldb;
+}
+
+void
+Ns2CalendarScheduler::insert2(Ns2CalendarScheduler::BucketItem* e)
+{
+ // Same as insert, but for inserts e *before* any same-time-events, if
+ // there should be any. Since it is used only by CalendarScheduler::newwidth(),
+ // some important checks present in insert() need not be performed.
+
+ int i = CALENDAR_HASH(e->event.key);
+ BucketItem *head = buckets_[i].list_;
+ BucketItem *before=0;
+ if (!head) {
+ buckets_[i].list_ = e;
+ e->next_ = e->prev_ = e;
+ ++stat_qsize_;
+ ++buckets_[i].count_;
+ } else {
+ bool newhead;
+ if (e->event.key > head->prev_->event.key) { //strict LIFO, so > and not >=
+ // insert at the tail
+ before = head;
+ newhead = false;
+ } else {
+ // insert event in time sorted order, LIFO for sim-time events
+ for (before = head; e->event.key > before->event.key; before = before->next_)
+ ;
+ newhead = (before == head);
+ }
+
+ e->next_ = before;
+ e->prev_ = before->prev_;
+ before->prev_ = e;
+ e->prev_->next_ = e;
+ if (newhead) {
+ buckets_[i].list_ = e;
+ //assert(e->time_ <= e->next_->time_);
+ }
+
+ if (e != e->next_ && e->next_->event.key != e->event.key) {
+ // unique timing
+ ++stat_qsize_;
+ ++buckets_[i].count_;
+ }
+ }
+ //assert(e == buckets_[i].list_ || e->prev_->time_ <= e->time_);
+ //assert(e == buckets_[i].list_->prev_ || e->next_->time_ >= e->time_);
+
+ ++qsize_;
+ // no need to check resizing
+}
+
+uint64_t
+Ns2CalendarScheduler::newwidth(int newsize)
+{
+ if (adjust_new_width_interval_) {
+ time_to_newwidth_ = adjust_new_width_interval_;
+ if (avg_gap_ > 0) return avg_gap_*4;
+ }
+ int i;
+ int max_bucket = 0; // index of the fullest bucket
+ for (i = 1; i < nbuckets_; ++i) {
+ if (buckets_[i].count_ > buckets_[max_bucket].count_)
+ max_bucket = i;
+ }
+ int nsamples = buckets_[max_bucket].count_;
+
+ if (nsamples <= 4) return width_;
+
+ uint64_t nw = (buckets_[max_bucket].list_->prev_->event.key.m_ts
+ - buckets_[max_bucket].list_->event.key.m_ts) * 4;
+
+ nw /= ((newsize < nsamples) ? newsize : nsamples); // min (newsize, nsamples)
+
+ nw = std::max (nw, min_bin_width_);
+
+ return nw;
+}
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/ns2-calendar-scheduler.h Tue Jan 20 11:41:57 2009 -0500
@@ -0,0 +1,100 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 1997 David Wetherall
+ * Copyright (c) 2005 David Wei
+ * Copyright (c) 2009 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * David Wetherall <djw@juniper.lcs.mit.edu>: originally, in ns-2, back in 1997
+ * David X. Wei: optimizations in ns-2.28
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>: port to ns-3
+ */
+
+#ifndef NS2_CALENDAR_SCHEDULER_H
+#define NS2_CALENDAR_SCHEDULER_H
+
+#include "scheduler.h"
+#include <stdint.h>
+#include <list>
+
+namespace ns3 {
+
+class EventImpl;
+
+/**
+ * \ingroup scheduler
+ * \brief a calendar queue event scheduler
+ *
+ * This event scheduler is a copy/paste of the ns2.29 calendar scheduler.
+ */
+class Ns2CalendarScheduler : public Scheduler
+{
+public:
+ static TypeId GetTypeId (void);
+
+ Ns2CalendarScheduler ();
+ virtual ~Ns2CalendarScheduler ();
+
+ virtual void Insert (const Event &ev);
+ virtual bool IsEmpty (void) const;
+ virtual Event PeekNext (void) const;
+ virtual Event RemoveNext (void);
+ virtual void Remove (const Event &ev);
+
+private:
+ struct BucketItem {
+ ns3::Scheduler::Event event;
+ struct BucketItem *next_;
+ struct BucketItem *prev_;
+ };
+ struct Bucket {
+ struct BucketItem *list_;
+ int count_;
+ };
+
+ void reinit(int nbuck, uint64_t bwidth, Scheduler::EventKey start);
+ void resize(int newsize, Scheduler::EventKey start);
+ uint64_t newwidth(int newsize);
+ void insert2 (Ns2CalendarScheduler::BucketItem *e);
+ Ns2CalendarScheduler::BucketItem *head (void);
+
+
+ uint64_t min_bin_width_; // minimum bin width for Calendar Queue
+ unsigned int adjust_new_width_interval_; // The interval (in unit of resize time) for adjustment of bin width. A zero value disables automatic bin width adjustment
+ unsigned time_to_newwidth_; // how many time we failed to adjust the width based on snoopy-queue
+ long unsigned head_search_;
+ long unsigned insert_search_;
+ int round_num_;
+ long int gap_num_; //the number of gap samples in this window (in process of calculation)
+ uint64_t last_time_; //the departure time of first event in this window
+ int64_t avg_gap_; //the average gap in last window (finished calculation)
+
+ uint64_t width_;
+ uint64_t diff0_, diff1_, diff2_; /* wrap-around checks */
+
+ int stat_qsize_; /* # of distinct priorities in queue*/
+ int nbuckets_;
+ int lastbucket_;
+ int top_threshold_;
+ int bot_threshold_;
+ int qsize_;
+ struct Bucket *buckets_;
+ Scheduler::EventKey cal_clock_;
+};
+
+} // namespace ns3
+
+#endif /* NS2_CALENDAR_SCHEDULER_H */
--- a/src/simulator/scheduler.h Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/scheduler.h Tue Jan 20 11:41:57 2009 -0500
@@ -115,6 +115,28 @@
return false;
}
}
+inline bool operator != (const Scheduler::EventKey &a, const Scheduler::EventKey &b)
+{
+ return a.m_uid != b.m_uid;
+}
+inline bool operator > (const Scheduler::EventKey &a, const Scheduler::EventKey &b)
+{
+ if (a.m_ts > b.m_ts)
+ {
+ return true;
+ }
+ else if (a.m_ts == b.m_ts &&
+ a.m_uid > b.m_uid)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
inline bool operator < (const Scheduler::Event &a, const Scheduler::Event &b)
{
--- a/src/simulator/simulator.cc Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/simulator.cc Tue Jan 20 11:41:57 2009 -0500
@@ -17,11 +17,13 @@
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
-
+#include "ns3/core-config.h"
#include "simulator.h"
#include "simulator-impl.h"
#include "default-simulator-impl.h"
-#include "realtime-simulator-impl.h"
+#ifdef HAVE_PTHREAD_H
+# include "realtime-simulator-impl.h"
+#endif
#include "scheduler.h"
#include "event-impl.h"
@@ -314,6 +316,8 @@
#include "list-scheduler.h"
#include "heap-scheduler.h"
#include "map-scheduler.h"
+#include "calendar-scheduler.h"
+#include "ns2-calendar-scheduler.h"
namespace ns3 {
@@ -740,6 +744,20 @@
}
Simulator::Destroy ();
+ Simulator::SetScheduler (CreateObject<CalendarScheduler> ());
+ if (!RunOneTest ())
+ {
+ result = false;
+ }
+ Simulator::Destroy ();
+
+ Simulator::SetScheduler (CreateObject<Ns2CalendarScheduler> ());
+ if (!RunOneTest ())
+ {
+ result = false;
+ }
+ Simulator::Destroy ();
+
Simulator::Schedule (Seconds (0.0), &foo0);
Simulator::Schedule (Seconds (0.0), &foo1, 0);
Simulator::Schedule (Seconds (0.0), &foo2, 0, 0);
--- a/src/simulator/simulator.h Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/simulator.h Tue Jan 20 11:41:57 2009 -0500
@@ -97,8 +97,8 @@
static void Destroy (void);
/**
- * If there any any events lefts to be scheduled and simulation time
- * has not yet reached the "stop time" (see Simulator::Stop()),
+ * If there are no more events lefts to be scheduled, or if simulation
+ * time has already reached the "stop time" (see Simulator::Stop()),
* return true. Return false otherwise.
*/
static bool IsFinished (void);
--- a/src/simulator/wscript Tue Jan 13 17:17:37 2009 -0500
+++ b/src/simulator/wscript Tue Jan 20 11:41:57 2009 -0500
@@ -49,6 +49,7 @@
'map-scheduler.cc',
'heap-scheduler.cc',
'calendar-scheduler.cc',
+ 'ns2-calendar-scheduler.cc',
'event-impl.cc',
'simulator.cc',
'default-simulator-impl.cc',
@@ -73,6 +74,7 @@
'map-scheduler.h',
'heap-scheduler.h',
'calendar-scheduler.h',
+ 'ns2-calendar-scheduler.h',
'simulation-singleton.h',
'timer.h',
'timer-impl.h',
Binary file waf has changed
--- a/wscript Tue Jan 13 17:17:37 2009 -0500
+++ b/wscript Tue Jan 20 11:41:57 2009 -0500
@@ -53,9 +53,6 @@
shutil.rmtree("doc/latex", True)
shutil.rmtree("nsc", True)
- if not os.path.exists("bindings/python/pybindgen"):
- raise Utils.WafError("Missing pybindgen checkout; run './waf configure --pybindgen-checkout' first.")
-
## build the name of the traces subdirectory. Will be something like
## ns-3-dev-ref-traces
traces_name = APPNAME + '-' + VERSION + regression.REGRESSION_SUFFIX
@@ -197,9 +194,7 @@
variant_name = Options.options.build_profile
if Options.options.regression_traces is not None:
- variant_env['REGRESSION_TRACES'] = os.path.join("..", Options.options.regression_traces)
- else:
- variant_env['REGRESSION_TRACES'] = None
+ variant_env['REGRESSION_TRACES'] = os.path.abspath(Options.options.regression_traces)
if Options.options.enable_gcov:
variant_name += '-gcov'
@@ -309,33 +304,19 @@
continue
if os.path.isdir(os.path.join("scratch", filename)):
obj = bld.create_ns3_program(filename, all_modules)
- obj.path = obj.path.find_dir('scratch')
- obj.find_sources_in_dirs(filename)
- obj.target = os.path.join(filename, filename)
+ obj.path = obj.path.find_dir('scratch').find_dir(filename)
+ obj.find_sources_in_dirs('.')
+ obj.target = filename
obj.name = obj.target
elif filename.endswith(".cc"):
name = filename[:-len(".cc")]
obj = bld.create_ns3_program(name, all_modules)
- obj.source = "scratch/%s" % filename
- obj.target = "scratch/%s" % name
+ obj.path = obj.path.find_dir('scratch')
+ obj.source = filename
+ obj.target = name
obj.name = obj.target
-##
-## This replacement spawn function increases the maximum command line length to 32k
-##
-def _exec_command_interact_win32(s):
- if Params.g_verbose:
- print s
- startupinfo = subprocess.STARTUPINFO()
- startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
- proc = subprocess.Popen(s, shell=False, startupinfo=startupinfo)
- stat = proc.wait()
- if stat & 0xff:
- return stat | 0x80
- return stat >> 8
-
-
def build(bld):
if Options.options.no_task_lines:
import Runner
@@ -343,10 +324,6 @@
pass
Runner.printout = null_printout
- if sys.platform == 'win32':
- import Runner
- Runner.exec_command = _exec_command_interact_win32
-
Options.cwd_launch = bld.path.abspath()
bld.create_ns3_program = types.MethodType(create_ns3_program, bld)
bld.create_suid_program = types.MethodType(create_suid_program, bld)
@@ -436,7 +413,7 @@
# nothing more; this greatly speeds up compilation when all you
# want to do is run a test program.
if not Options.options.compile_targets:
- Options.options.compile_targets = program_name
+ Options.options.compile_targets = os.path.basename(program_name)
@@ -462,15 +439,11 @@
if not env['DIFF']:
raise Utils.WafError("Cannot run regression tests: the 'diff' program is not installed.")
- _dir = os.getcwd()
- os.chdir("regression")
regression_traces = env['REGRESSION_TRACES']
if not regression_traces:
- regression_traces = None
- try:
- retval = regression.run_regression(regression_traces)
- finally:
- os.chdir(_dir)
+ raise Utils.WafError("Cannot run regression tests: reference traces directory not given"
+ " (--with-regression-traces configure option)")
+ retval = regression.run_regression(regression_traces)
if retval:
sys.exit(retval)
--- a/wutils.py Tue Jan 13 17:17:37 2009 -0500
+++ b/wutils.py Tue Jan 20 11:41:57 2009 -0500
@@ -38,9 +38,30 @@
return cmd
+if hasattr(os.path, "relpath"):
+ relpath = os.path.relpath # since Python 2.6
+else:
+ def relpath(path, start=os.path.curdir):
+ """Return a relative version of a path"""
+
+ if not path:
+ raise ValueError("no path specified")
+
+ start_list = os.path.abspath(start).split(os.path.sep)
+ path_list = os.path.abspath(path).split(os.path.sep)
+
+ # Work out how much of the filepath is shared by start and path.
+ i = len(os.path.commonprefix([start_list, path_list]))
+
+ rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+ if not rel_list:
+ return os.path.curdir
+ return os.path.join(*rel_list)
+
def find_program(program_name, env):
launch_dir = os.path.abspath(Options.cwd_launch)
+ top_dir = os.path.abspath(Options.launch_dir)
found_programs = []
for obj in Build.bld.all_task_gen:
if not getattr(obj, 'is_ns3_program', False):
@@ -51,8 +72,11 @@
or obj.path.abspath(env).startswith(launch_dir)):
continue
- found_programs.append(obj.target)
- if obj.target == program_name:
+ name1 = obj.target
+ name2 = os.path.join(relpath(obj.path.abspath(), top_dir), obj.target)
+ names = [name1, name2]
+ found_programs.extend(names)
+ if program_name in names:
return obj
raise ValueError("program '%s' not found; available programs are: %r"
% (program_name, found_programs))
@@ -93,10 +117,10 @@
return proc_env
-def run_argv(argv, os_env=None):
+def run_argv(argv, os_env=None, cwd=None):
proc_env = get_proc_env(os_env)
#env = Build.bld.env
- retval = subprocess.Popen(argv, env=proc_env).wait()
+ retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
if retval:
raise Utils.WafError("Command %s exited with code %i" % (argv, retval))
return retval
@@ -143,7 +167,7 @@
execvec = shlex.split(command_template % (program_node.abspath(env),))
return program_name, execvec
-def run_program(program_string, command_template=None):
+def run_program(program_string, command_template=None, cwd=None):
"""
if command_template is not None, then program_string == program
name and argv is given by command_template with %s replaced by the
@@ -151,34 +175,23 @@
a shell command with first name being the program name.
"""
dummy_program_name, execvec = get_run_program(program_string, command_template)
- former_cwd = os.getcwd()
- if (Options.options.cwd_launch):
- os.chdir(Options.options.cwd_launch)
- else:
- os.chdir(Options.cwd_launch)
- try:
- retval = run_argv(execvec)
- finally:
- os.chdir(former_cwd)
-
- return retval
+ if cwd is None:
+ if (Options.options.cwd_launch):
+ cwd = Options.options.cwd_launch
+ else:
+ cwd = Options.cwd_launch
+ return run_argv(execvec, cwd=cwd)
def run_python_program(program_string):
env = Build.bld.env
execvec = shlex.split(program_string)
-
- former_cwd = os.getcwd()
- if (Options.options.cwd_launch):
- os.chdir(Options.options.cwd_launch)
- else:
- os.chdir(Options.cwd_launch)
- try:
- retval = run_argv([env['PYTHON']] + execvec)
- finally:
- os.chdir(former_cwd)
-
- return retval
+ if cwd is None:
+ if (Options.options.cwd_launch):
+ cwd = Options.options.cwd_launch
+ else:
+ cwd = Options.cwd_launch
+ return run_argv([env['PYTHON']] + execvec, cwd=cwd)