1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/samples/main-callback.cc Tue Aug 29 17:47:17 2006 +0200
1.3 @@ -0,0 +1,58 @@
1.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
1.5 +#include "yans/callback.h"
1.6 +#include <cassert>
1.7 +#include <iostream>
1.8 +
1.9 +using namespace yans;
1.10 +
1.11 +static double
1.12 +cb_one (double a, double b)
1.13 +{
1.14 + std::cout << "invoke cb_one a=" << a << ", b=" << b << std::endl;
1.15 + return a;
1.16 +}
1.17 +
1.18 +class MyCb {
1.19 +public:
1.20 + int cb_two (double a) {
1.21 + std::cout << "invoke cb_two a=" << a << std::endl;
1.22 + return -5;
1.23 + }
1.24 +};
1.25 +
1.26 +
1.27 +int main (int argc, char *argv[])
1.28 +{
1.29 + // return type: double
1.30 + // first arg type: double
1.31 + // second arg type: double
1.32 + Callback<double, double, double> one;
1.33 + // build callback instance which points to cb_one function
1.34 + one = make_callback (&cb_one);
1.35 + // this is not a null callback
1.36 + assert (!one.is_null ());
1.37 + // invoke cb_one function through callback instance
1.38 + double ret_one;
1.39 + ret_one = one (10.0, 20.0);
1.40 +
1.41 + // return type: int
1.42 + // first arg type: double
1.43 + Callback<int, double> two;
1.44 + MyCb cb;
1.45 + // build callback instance which points to MyCb::cb_two
1.46 + two = make_callback (&MyCb::cb_two, &cb);
1.47 + // this is not a null callback
1.48 + assert (!two.is_null ());
1.49 + // invoke MyCb::cb_two through callback instance
1.50 + int ret_two;
1.51 + ret_two = two (10.0);
1.52 +
1.53 + two = make_null_callback<int, double> ();
1.54 + // invoking a null callback is just like
1.55 + // invoking a null function pointer:
1.56 + // it will crash.
1.57 + //int ret_two_null = two (20.0);
1.58 + assert (two.is_null ());
1.59 +
1.60 + return 0;
1.61 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/samples/main-event.cc Tue Aug 29 17:47:17 2006 +0200
2.3 @@ -0,0 +1,42 @@
2.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
2.5 +#include "yans/event.h"
2.6 +#include "yans/event.tcc"
2.7 +#include <iostream>
2.8 +
2.9 +using namespace yans;
2.10 +
2.11 +class MyModel {
2.12 +public:
2.13 + void deal_with_event (double event_value);
2.14 +};
2.15 +
2.16 +void
2.17 +MyModel::deal_with_event (double value)
2.18 +{
2.19 + std::cout << "Member method received event." << std::endl;
2.20 +}
2.21 +
2.22 +static void
2.23 +random_function (void)
2.24 +{
2.25 + std::cout << "Function received event." << std::endl;
2.26 +}
2.27 +
2.28 +
2.29 +int main (int argc, char *argv[])
2.30 +{
2.31 + Event ev;
2.32 + // create event to forward to random_function
2.33 + ev = make_event (&random_function);
2.34 + // set cancel bit to on
2.35 + ev.cancel ();
2.36 + // try to invoke the random_function through the event.
2.37 + // This does nothing since cancel bit is on.
2.38 + ev ();
2.39 + MyModel model;
2.40 + // create event to forward to MyModel::deal_with_event
2.41 + // on the class instance "model".
2.42 + ev = make_event (&MyModel::deal_with_event, &model, 10.0);
2.43 + // invoke member method through the event.
2.44 + ev ();
2.45 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/samples/main-packet.cc Tue Aug 29 17:47:17 2006 +0200
3.3 @@ -0,0 +1,100 @@
3.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
3.5 +#include "yans/packet.h"
3.6 +#include "yans/chunk.h"
3.7 +#include <iostream>
3.8 +
3.9 +using namespace yans;
3.10 +
3.11 +/* A sample Chunk implementation
3.12 + */
3.13 +class MyChunk : public Chunk {
3.14 +public:
3.15 + MyChunk ();
3.16 + virtual ~MyChunk ();
3.17 +
3.18 + void set_data (uint16_t data);
3.19 + uint16_t get_data (void) const;
3.20 +private:
3.21 + virtual void print (std::ostream *os) const;
3.22 + virtual void add_to (Buffer *buffer) const;
3.23 + virtual void peek_from (Buffer const *buffer);
3.24 + virtual void remove_from (Buffer *buffer);
3.25 +
3.26 + uint16_t m_data;
3.27 +};
3.28 +
3.29 +MyChunk::MyChunk ()
3.30 +{}
3.31 +MyChunk::~MyChunk ()
3.32 +{}
3.33 +void
3.34 +MyChunk::print (std::ostream *os) const
3.35 +{
3.36 + *os << "MyChunk data=" << m_data << std::endl;
3.37 +}
3.38 +void
3.39 +MyChunk::add_to (Buffer *buffer) const
3.40 +{
3.41 + // reserve 2 bytes at head of buffer
3.42 + buffer->add_at_start (2);
3.43 + Buffer::Iterator i = buffer->begin ();
3.44 + // serialize in head of buffer
3.45 + i.write_hton_u16 (m_data);
3.46 +}
3.47 +void
3.48 +MyChunk::peek_from (Buffer const *buffer)
3.49 +{
3.50 + Buffer::Iterator i = buffer->begin ();
3.51 + // deserialize from head of buffer
3.52 + m_data = i.read_ntoh_u16 ();
3.53 +}
3.54 +void
3.55 +MyChunk::remove_from (Buffer *buffer)
3.56 +{
3.57 + // remove deserialized data
3.58 + buffer->remove_at_start (2);
3.59 +}
3.60 +
3.61 +void
3.62 +MyChunk::set_data (uint16_t data)
3.63 +{
3.64 + m_data = data;
3.65 +}
3.66 +uint16_t
3.67 +MyChunk::get_data (void) const
3.68 +{
3.69 + return m_data;
3.70 +}
3.71 +
3.72 +/* A sample Tag implementation
3.73 + */
3.74 +struct MyTag {
3.75 + uint16_t m_stream_id;
3.76 +};
3.77 +
3.78 +
3.79 +static void
3.80 +receive (Packet p)
3.81 +{
3.82 + MyChunk my;
3.83 + p.peek (&my);
3.84 + p.remove (&my);
3.85 + std::cout << "received data=" << my.get_data () << std::endl;
3.86 + struct MyTag my_tag;
3.87 + p.peek_tag (&my_tag);
3.88 +}
3.89 +
3.90 +
3.91 +int main (int argc, char *argv[])
3.92 +{
3.93 + Packet p;
3.94 + MyChunk my;
3.95 + my.set_data (2);
3.96 + std::cout << "send data=2" << std::endl;
3.97 + p.add (&my);
3.98 + struct MyTag my_tag;
3.99 + my_tag.m_stream_id = 5;
3.100 + p.add_tag (&my_tag);
3.101 + receive (p);
3.102 + return 0;
3.103 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/samples/main-simulator.cc Tue Aug 29 17:47:17 2006 +0200
4.3 @@ -0,0 +1,46 @@
4.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
4.5 +#include "yans/event.h"
4.6 +#include "yans/event.tcc"
4.7 +#include "yans/simulator.h"
4.8 +#include <iostream>
4.9 +
4.10 +using namespace yans;
4.11 +
4.12 +class MyModel {
4.13 +public:
4.14 + void start (void);
4.15 +private:
4.16 + void deal_with_event (double event_value);
4.17 +};
4.18 +
4.19 +void
4.20 +MyModel::start (void)
4.21 +{
4.22 + Simulator::schedule_rel_s (10.0, make_event (&MyModel::deal_with_event,
4.23 + this, Simulator::now_s ()));
4.24 +}
4.25 +void
4.26 +MyModel::deal_with_event (double value)
4.27 +{
4.28 + std::cout << "Member method received event at " << Simulator::now_s () << " started at " << value << std::endl;
4.29 +}
4.30 +
4.31 +static void
4.32 +random_function (MyModel *model)
4.33 +{
4.34 + std::cout << "random function received event at " << Simulator::now_s () << std::endl;
4.35 + model->start ();
4.36 +}
4.37 +
4.38 +
4.39 +int main (int argc, char *argv[])
4.40 +{
4.41 + MyModel model;
4.42 +
4.43 + Simulator::schedule_rel_s (10.0, make_event (&random_function,
4.44 + &model));
4.45 +
4.46 + Simulator::run ();
4.47 +
4.48 + Simulator::destroy ();
4.49 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/samples/main-trace.cc Tue Aug 29 17:47:17 2006 +0200
5.3 @@ -0,0 +1,60 @@
5.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
5.5 +#include "yans/trace-container.h"
5.6 +#include "yans/ui-traced-variable.tcc"
5.7 +#include "yans/packet-logger.h"
5.8 +#include "yans/trace-stream.h"
5.9 +#include "yans/pcap-writer.h"
5.10 +#include <iostream>
5.11 +
5.12 +using namespace yans;
5.13 +
5.14 +PacketLogger a;
5.15 +UiTracedVariable<unsigned short> b;
5.16 +TraceStream c;
5.17 +CallbackLogger<double, int> d;
5.18 +
5.19 +void
5.20 +register_all_trace_sources (TraceContainer *container)
5.21 +{
5.22 + container->register_packet_logger ("source-a", &a);
5.23 + container->register_ui_variable ("source-b", &b);
5.24 + container->register_stream ("source-c", &c);
5.25 + container->register_callback ("source-d", &d);
5.26 +}
5.27 +void
5.28 +generate_trace_events (void)
5.29 +{
5.30 + // log en empty packet
5.31 + a.log (Packet ());
5.32 + b = 10;
5.33 + b += 100;
5.34 + b += 50;
5.35 + b = (unsigned short) -20;
5.36 + c << "this is a simple test b=" << b << std::endl;
5.37 + d (3.1415, 3);
5.38 +}
5.39 +
5.40 +void
5.41 +variable_event (uint64_t old, uint64_t cur)
5.42 +{}
5.43 +
5.44 +void
5.45 +callback_event (double a, int b)
5.46 +{}
5.47 +
5.48 +
5.49 +int main (int argc, char *argv[])
5.50 +{
5.51 + TraceContainer traces;
5.52 + register_all_trace_sources (&traces);
5.53 + PcapWriter pcap;
5.54 + pcap.open ("trace-test.log");
5.55 + pcap.write_header_ethernet ();
5.56 + traces.set_packet_logger_callback ("source-a",
5.57 + make_callback (&PcapWriter::write_packet, &pcap));
5.58 + traces.set_ui_variable_callback ("source-b", make_callback (&variable_event));
5.59 + traces.set_stream ("source-c", &std::cout);
5.60 + traces.set_callback ("source-d", make_callback (&callback_event));
5.61 + generate_trace_events ();
5.62 + return 0;
5.63 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/utils/bench-packets.cc Tue Aug 29 17:47:17 2006 +0200
6.3 @@ -0,0 +1,135 @@
6.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
6.5 +/*
6.6 + * Copyright (c) 2006 INRIA
6.7 + * All rights reserved.
6.8 + *
6.9 + * This program is free software; you can redistribute it and/or modify
6.10 + * it under the terms of the GNU General Public License version 2 as
6.11 + * published by the Free Software Foundation;
6.12 + *
6.13 + * This program is distributed in the hope that it will be useful,
6.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.16 + * GNU General Public License for more details.
6.17 + *
6.18 + * You should have received a copy of the GNU General Public License
6.19 + * along with this program; if not, write to the Free Software
6.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6.21 + *
6.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
6.23 + */
6.24 +#include "yans/wall-clock-ms.h"
6.25 +#include "yans/packet.h"
6.26 +#include "yans/chunk-constant-data.h"
6.27 +#include "yans/chunk-udp.h"
6.28 +#include "yans/chunk-ipv4.h"
6.29 +#include <iostream>
6.30 +
6.31 +using namespace yans;
6.32 +
6.33 +static void
6.34 +bench_ptr_a (uint32_t n)
6.35 +{
6.36 + ChunkConstantData data = ChunkConstantData (2000, 1);
6.37 + ChunkUdp udp;
6.38 + ChunkIpv4 ipv4;
6.39 +
6.40 + for (uint32_t i = 0; i < n; i++) {
6.41 + Packet p;
6.42 + p.add (&data);
6.43 + p.add (&udp);
6.44 + p.add (&ipv4);
6.45 + Packet o = p;
6.46 + o.peek (&ipv4);
6.47 + o.remove (&ipv4);
6.48 + o.peek (&udp);
6.49 + o.remove (&udp);
6.50 + o.peek (&data);
6.51 + o.remove (&data);
6.52 + }
6.53 +}
6.54 +
6.55 +static void
6.56 +bench_ptr_b (uint32_t n)
6.57 +{
6.58 + ChunkConstantData data = ChunkConstantData (2000, 1);
6.59 + ChunkUdp udp;
6.60 + ChunkIpv4 ipv4;
6.61 +
6.62 + for (uint32_t i = 0; i < n; i++) {
6.63 + Packet p;
6.64 + p.add (&data);
6.65 + p.add (&udp);
6.66 + p.add (&ipv4);
6.67 + }
6.68 +}
6.69 +
6.70 +static void
6.71 +ptr_c2 (Packet p)
6.72 +{
6.73 + ChunkConstantData data = ChunkConstantData (2000, 1);
6.74 + ChunkUdp udp;
6.75 +
6.76 + p.peek (&udp);
6.77 + p.remove (&udp);
6.78 + p.peek (&data);
6.79 + p.remove (&data);
6.80 +}
6.81 +
6.82 +static void
6.83 +ptr_c1 (Packet p)
6.84 +{
6.85 + ChunkIpv4 ipv4;
6.86 + p.peek (&ipv4);
6.87 + p.remove (&ipv4);
6.88 + ptr_c2 (p);
6.89 +}
6.90 +
6.91 +static void
6.92 +bench_ptr_c (uint32_t n)
6.93 +{
6.94 + ChunkConstantData data = ChunkConstantData (2000, 1);
6.95 + ChunkUdp udp;
6.96 + ChunkIpv4 ipv4;
6.97 +
6.98 + for (uint32_t i = 0; i < n; i++) {
6.99 + Packet p;
6.100 + p.add (&data);
6.101 + p.add (&udp);
6.102 + p.add (&ipv4);
6.103 + ptr_c1 (p);
6.104 + }
6.105 +}
6.106 +
6.107 +
6.108 +static void
6.109 +run_bench (void (*bench) (uint32_t), uint32_t n, char const *name)
6.110 +{
6.111 + WallClockMs time;
6.112 + time.start ();
6.113 + (*bench) (n);
6.114 + unsigned long long delta_ms = time.end ();
6.115 + double ps = n;
6.116 + ps *= 1000;
6.117 + ps /= delta_ms;
6.118 + std::cout << name<<"=" << ps << " packets/s" << std::endl;
6.119 +}
6.120 +
6.121 +int main (int argc, char *argv[])
6.122 +{
6.123 + uint32_t n = 0;
6.124 + while (argc > 0) {
6.125 + if (strncmp ("--n=", argv[0],strlen ("--n=")) == 0) {
6.126 + char const *n_ascii = argv[0] + strlen ("--n=");
6.127 + n = atoi (n_ascii);
6.128 + }
6.129 + argc--;
6.130 + argv++;
6.131 + }
6.132 +
6.133 + run_bench (&bench_ptr_a, n, "a");
6.134 + run_bench (&bench_ptr_b, n, "b");
6.135 + run_bench (&bench_ptr_c, n, "c");
6.136 +
6.137 + return 0;
6.138 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/utils/bench-simulator.cc Tue Aug 29 17:47:17 2006 +0200
7.3 @@ -0,0 +1,148 @@
7.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
7.5 +/*
7.6 + * Copyright (c) 2006 INRIA
7.7 + * All rights reserved.
7.8 + *
7.9 + * This program is free software; you can redistribute it and/or modify
7.10 + * it under the terms of the GNU General Public License version 2 as
7.11 + * published by the Free Software Foundation;
7.12 + *
7.13 + * This program is distributed in the hope that it will be useful,
7.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.16 + * GNU General Public License for more details.
7.17 + *
7.18 + * You should have received a copy of the GNU General Public License
7.19 + * along with this program; if not, write to the Free Software
7.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7.21 + *
7.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7.23 + */
7.24 +
7.25 +#include "yans/simulator.h"
7.26 +#include "yans/event.h"
7.27 +#include "yans/event.tcc"
7.28 +#include "yans/wall-clock-ms.h"
7.29 +#include <iostream>
7.30 +#include <fstream>
7.31 +#include <vector>
7.32 +
7.33 +using namespace yans;
7.34 +
7.35 +
7.36 +bool g_debug = false;
7.37 +
7.38 +class Bench {
7.39 +public:
7.40 + void read_distribution (std::istream &istream);
7.41 + void set_total (uint32_t total);
7.42 + void bench (void);
7.43 +private:
7.44 + void cb (void);
7.45 + std::vector<uint64_t> m_distribution;
7.46 + std::vector<uint64_t>::const_iterator m_current;
7.47 + uint32_t m_n;
7.48 + uint32_t m_total;
7.49 +};
7.50 +
7.51 +void
7.52 +Bench::set_total (uint32_t total)
7.53 +{
7.54 + m_total = total;
7.55 +}
7.56 +
7.57 +void
7.58 +Bench::read_distribution (std::istream &input)
7.59 +{
7.60 + double data;
7.61 + while (!input.eof ()) {
7.62 + if (input >> data) {
7.63 + uint64_t us = (uint64_t) (data * 1000000);
7.64 + m_distribution.push_back (us);
7.65 + } else {
7.66 + input.clear ();
7.67 + std::string line;
7.68 + input >> line;
7.69 + }
7.70 + }
7.71 +}
7.72 +
7.73 +void
7.74 +Bench::bench (void)
7.75 +{
7.76 + WallClockMs time;
7.77 + double init, simu;
7.78 + time.start ();
7.79 + for (std::vector<uint64_t>::const_iterator i = m_distribution.begin ();
7.80 + i != m_distribution.end (); i++) {
7.81 + Simulator::schedule_rel_us (*i, make_event (&Bench::cb, this));
7.82 + }
7.83 + init = time.end ();
7.84 +
7.85 + m_current = m_distribution.begin ();
7.86 +
7.87 + time.start ();
7.88 + Simulator::run ();
7.89 + simu = time.end ();
7.90 +
7.91 + std::cout <<
7.92 + "init n=" << m_distribution.size () << ", time=" << init << "s" << std::endl <<
7.93 + "simu n=" << m_n << ", time=" <<simu << "s" << std::endl <<
7.94 + "init " << ((double)m_distribution.size ()) / init << " insert/s, avg insert=" <<
7.95 + init / ((double)m_distribution.size ())<< "s" << std::endl <<
7.96 + "simu " << ((double)m_n) / simu<< " hold/s, avg hold=" <<
7.97 + simu / ((double)m_n) << "s" << std::endl
7.98 + ;
7.99 +}
7.100 +
7.101 +void
7.102 +Bench::cb (void)
7.103 +{
7.104 + if (m_n > m_total) {
7.105 + return;
7.106 + }
7.107 + if (m_current == m_distribution.end ()) {
7.108 + m_current = m_distribution.begin ();
7.109 + }
7.110 + if (g_debug) {
7.111 + std::cerr << "event at " << Simulator::now_s () << std::endl;
7.112 + }
7.113 + Simulator::schedule_rel_us (*m_current, make_event (&Bench::cb, this));
7.114 + m_current++;
7.115 + m_n++;
7.116 +}
7.117 +
7.118 +int main (int argc, char *argv[])
7.119 +{
7.120 + char const *filename = argv[1];
7.121 + std::istream *input;
7.122 + argc-=2;
7.123 + argv+= 2;
7.124 + if (strcmp (filename, "-") == 0) {
7.125 + input = &std::cin;
7.126 + } else {
7.127 + input = new std::ifstream (filename);
7.128 + }
7.129 + while (argc > 0) {
7.130 + if (strcmp ("--list", argv[0]) == 0) {
7.131 + Simulator::set_linked_list ();
7.132 + } else if (strcmp ("--heap", argv[0]) == 0) {
7.133 + Simulator::set_binary_heap ();
7.134 + } else if (strcmp ("--map", argv[0]) == 0) {
7.135 + Simulator::set_std_map ();
7.136 + } else if (strcmp ("--debug", argv[0]) == 0) {
7.137 + g_debug = true;
7.138 + } else if (strncmp ("--log=", argv[0],strlen ("--log=")) == 0) {
7.139 + char const *filename = argv[0] + strlen ("--log=");
7.140 + Simulator::enable_log_to (filename);
7.141 + }
7.142 + argc--;
7.143 + argv++;
7.144 + }
7.145 + Bench *bench = new Bench ();
7.146 + bench->read_distribution (*input);
7.147 + bench->set_total (20000);
7.148 + bench->bench ();
7.149 +
7.150 + return 0;
7.151 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/utils/grid.py Tue Aug 29 17:47:17 2006 +0200
8.3 @@ -0,0 +1,1053 @@
8.4 +#!/usr/bin/env python
8.5 +
8.6 +import cairo
8.7 +import sys
8.8 +import re
8.9 +import gtk
8.10 +
8.11 +
8.12 +
8.13 +class DataRange:
8.14 + def __init__ (self, start = 0, end = 0, value = ''):
8.15 + self.start = start
8.16 + self.end = end
8.17 + self.value = value
8.18 +class EventString:
8.19 + def __init__ (self, at = 0, value = ''):
8.20 + self.at = at
8.21 + self.value = value
8.22 +class EventFloat:
8.23 + def __init__ (self, at = 0, value = 0.0):
8.24 + self.at = at
8.25 + self.value = value
8.26 +class EventInt:
8.27 + def __init__ (self, at = 0, value = 0.0):
8.28 + self.at = at
8.29 + self.value = value
8.30 +def ranges_cmp (a, b):
8.31 + return a.start - b.start
8.32 +def events_cmp (a,b):
8.33 + return a.at - b.at
8.34 +class TimelineDataRange:
8.35 + def __init__ (self, name = ''):
8.36 + self.name = name
8.37 + self.ranges = []
8.38 + return
8.39 + def __search (self, key):
8.40 + l = 0
8.41 + u = len (self.ranges)-1
8.42 + while l <= u:
8.43 + i = int ((l+u)/2)
8.44 + if key >= self.ranges[i].start and key <= self.ranges[i].end:
8.45 + return i
8.46 + elif key < self.ranges[i].start:
8.47 + u = i - 1
8.48 + else:
8.49 + # key > self.ranges[i].end
8.50 + l = i + 1
8.51 + return -1
8.52 + def add_range (self, range):
8.53 + self.ranges.append (range)
8.54 + def get_all (self):
8.55 + return self.ranges
8.56 + def get_ranges (self, start, end):
8.57 + s = self.__search (start)
8.58 + e = self.__search (end)
8.59 + if s == -1 and e == -1:
8.60 + return []
8.61 + elif s == -1:
8.62 + return self.ranges[0:e+1]
8.63 + elif e == -1:
8.64 + return self.ranges[s:len (self.ranges)]
8.65 + else:
8.66 + return self.ranges[s:e+1]
8.67 + def get_ranges_bounds (self, start, end):
8.68 + s = self.__search (start)
8.69 + e = self.__search (end)
8.70 + if s == -1 and e == -1:
8.71 + return (0,0)
8.72 + elif s == -1:
8.73 + return (0,e+1)
8.74 + elif e == -1:
8.75 + return (s, len (self.ranges))
8.76 + else:
8.77 + return (s,e+1)
8.78 + def sort (self):
8.79 + self.ranges.sort (ranges_cmp)
8.80 + def get_bounds (self):
8.81 + if len (self.ranges) > 0:
8.82 + lo = self.ranges[0].start
8.83 + hi = self.ranges[len (self.ranges)-1].end
8.84 + return (lo, hi)
8.85 + else:
8.86 + return (0,0)
8.87 +class TimelineEvent:
8.88 + def __init__ (self, name = ''):
8.89 + self.name = name
8.90 + self.events = []
8.91 + def __search (self, key):
8.92 + l = 0
8.93 + u = len (self.events)-1
8.94 + while l <= u:
8.95 + i = int ((l+u)/2)
8.96 + if key == self.events[i].at:
8.97 + return i
8.98 + elif key < self.events[i].at:
8.99 + u = i - 1
8.100 + else:
8.101 + # key > self.events[i].at
8.102 + l = i + 1
8.103 + return l
8.104 + def add_event (self, event):
8.105 + self.events.append (event)
8.106 + def get_events (self, start, end):
8.107 + s = self.__search (start)
8.108 + e = self.__search (end)
8.109 + return self.events[s:e+1]
8.110 + def get_events_bounds (self, start, end):
8.111 + s = self.__search (start)
8.112 + e = self.__search (end)
8.113 + return (s, e+1)
8.114 + def sort (self):
8.115 + self.events.sort (events_cmp)
8.116 + def get_bounds (self):
8.117 + if len (self.events) > 0:
8.118 + lo = self.events[0].at
8.119 + hi = self.events[-1].at
8.120 + return (lo,hi)
8.121 + else:
8.122 + return (0,0)
8.123 +
8.124 +class Timeline:
8.125 + def __init__ (self, name = ''):
8.126 + self.ranges = []
8.127 + self.event_str = []
8.128 + self.event_int = []
8.129 + self.name = name
8.130 + def get_range (self, name):
8.131 + for range in self.ranges:
8.132 + if range.name == name:
8.133 + return range
8.134 + timeline = TimelineDataRange (name)
8.135 + self.ranges.append (timeline)
8.136 + return timeline
8.137 + def get_event_str (self, name):
8.138 + for event_str in self.event_str:
8.139 + if event_str.name == name:
8.140 + return event_str
8.141 + timeline = TimelineEvent (name)
8.142 + self.event_str.append (timeline)
8.143 + return timeline
8.144 + def get_event_int (self, name):
8.145 + for event_int in self.event_int:
8.146 + if event_int.name == name:
8.147 + return event_int
8.148 + timeline = TimelineEvent (name)
8.149 + self.event_int.append (timeline)
8.150 + return timeline
8.151 + def get_ranges (self):
8.152 + return self.ranges
8.153 + def get_events_str (self):
8.154 + return self.event_str
8.155 + def get_events_int (self):
8.156 + return self.event_int
8.157 + def sort (self):
8.158 + for range in self.ranges:
8.159 + range.sort ()
8.160 + for event in self.event_int:
8.161 + event.sort ()
8.162 + for event in self.event_str:
8.163 + event.sort ()
8.164 + def get_bounds (self):
8.165 + lo = 0
8.166 + hi = 0
8.167 + for range in self.ranges:
8.168 + (range_lo, range_hi) = range.get_bounds ()
8.169 + if range_lo < lo:
8.170 + lo = range_lo
8.171 + if range_hi > hi:
8.172 + hi = range_hi
8.173 + for event_str in self.event_str:
8.174 + (ev_lo, ev_hi) = event_str.get_bounds ()
8.175 + if ev_lo < lo:
8.176 + lo = ev_lo
8.177 + if ev_hi > hi:
8.178 + hi = ev_hi
8.179 + for event_int in self.event_int:
8.180 + (ev_lo, ev_hi) = event_int.get_bounds ()
8.181 + if ev_lo < lo:
8.182 + lo = ev_lo
8.183 + if ev_hi > hi:
8.184 + hi = ev_hi
8.185 + return (lo, hi)
8.186 +class Timelines:
8.187 + def __init__ (self):
8.188 + self.timelines = []
8.189 + def get (self, name):
8.190 + for timeline in self.timelines:
8.191 + if timeline.name == name:
8.192 + return timeline
8.193 + timeline = Timeline (name)
8.194 + self.timelines.append (timeline)
8.195 + return timeline
8.196 + def get_all (self):
8.197 + return self.timelines
8.198 + def sort (self):
8.199 + for timeline in self.timelines:
8.200 + timeline.sort ()
8.201 + def get_bounds (self):
8.202 + lo = 0
8.203 + hi = 0
8.204 + for timeline in self.timelines:
8.205 + (t_lo, t_hi) = timeline.get_bounds ()
8.206 + if t_lo < lo:
8.207 + lo = t_lo
8.208 + if t_hi > hi:
8.209 + hi = t_hi
8.210 + return (lo, hi)
8.211 + def get_all_range_values (self):
8.212 + range_values = {}
8.213 + for timeline in self.timelines:
8.214 + for ranges in timeline.get_ranges ():
8.215 + for ran in ranges.get_all ():
8.216 + range_values[ran.value] = 1
8.217 + return range_values.keys ()
8.218 +class Color:
8.219 + def __init__ (self, r = 0.0, g = 0.0, b = 0.0):
8.220 + self.r = r
8.221 + self.g = g
8.222 + self.b = b
8.223 + def set (self, r, g, b):
8.224 + self.r = r
8.225 + self.g = g
8.226 + self.b = b
8.227 +class Colors:
8.228 + # XXX add more
8.229 + default_colors = [Color (1,0,0), Color (0,1,0), Color (0,0,1),Color (1,1,0), Color(1,0,1), Color (0,1,1)]
8.230 + def __init__ (self):
8.231 + self.__colors = {}
8.232 + def add (self, name, color):
8.233 + self.__colors[name] = color
8.234 + def lookup (self, name):
8.235 + if not self.__colors.has_key (name):
8.236 + self.add (name, self.default_colors.pop ())
8.237 + return self.__colors.get(name)
8.238 +
8.239 +
8.240 +class TopLegendRenderer:
8.241 + def __init__ (self):
8.242 + self.__padding = 10
8.243 + def set_padding (self, padding):
8.244 + self.__padding = padding
8.245 + def set_legends (self, legends, colors):
8.246 + self.__legends = legends
8.247 + self.__colors = colors
8.248 + def layout (self, width):
8.249 + self.__width = width
8.250 + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1,1)
8.251 + ctx = cairo.Context(surface)
8.252 + line_height = 0
8.253 + total_height = self.__padding
8.254 + line_used = self.__padding
8.255 + for legend in self.__legends:
8.256 + (t_width, t_height) = ctx.text_extents (legend)[2:4]
8.257 + item_width = self.__padding + self.__padding + t_width + self.__padding
8.258 + item_height = t_height + self.__padding
8.259 + if item_height > line_height:
8.260 + line_height = item_height
8.261 + if line_used + item_width > self.__width:
8.262 + line_used = self.__padding + item_width
8.263 + total_height += line_height
8.264 + else:
8.265 + line_used += item_width
8.266 + x = line_used - item_width
8.267 + total_height += line_height
8.268 + self.__height = total_height
8.269 +
8.270 + def get_height (self):
8.271 + return self.__height
8.272 + def draw (self, ctx):
8.273 + i = 0
8.274 + line_height = 0
8.275 + total_height = self.__padding
8.276 + line_used = self.__padding
8.277 + for legend in self.__legends:
8.278 + (t_width, t_height) = ctx.text_extents (legend)[2:4]
8.279 + item_width = self.__padding + self.__padding + t_width + self.__padding
8.280 + item_height = t_height + self.__padding
8.281 + if item_height > line_height:
8.282 + line_height = item_height
8.283 + if line_used + item_width > self.__width:
8.284 + line_used = self.__padding + item_width
8.285 + total_height += line_height
8.286 + else:
8.287 + line_used += item_width
8.288 + x = line_used - item_width
8.289 + ctx.rectangle (x, total_height, self.__padding, self.__padding)
8.290 + ctx.set_source_rgb (0,0,0)
8.291 + ctx.set_line_width (2)
8.292 + ctx.stroke_preserve ()
8.293 + ctx.set_source_rgb (self.__colors[i].r,
8.294 + self.__colors[i].g,
8.295 + self.__colors[i].b)
8.296 + ctx.fill ()
8.297 + ctx.move_to (x+self.__padding*2, total_height+t_height)
8.298 + ctx.set_source_rgb (0,0,0)
8.299 + ctx.show_text (legend)
8.300 + i += 1
8.301 +
8.302 + return
8.303 +
8.304 +class TimelinesRenderer:
8.305 + def __init__ (self):
8.306 + self.padding = 10
8.307 + return
8.308 + def get_height (self):
8.309 + return self.height
8.310 + def set_timelines (self, timelines, colors):
8.311 + self.timelines = timelines
8.312 + self.colors = colors
8.313 + def set_render_range (self, start, end):
8.314 + self.start = start
8.315 + self.end = end
8.316 + def get_data_x_start (self):
8.317 + return self.padding / 2 + self.left_width + self.padding + self.right_width + self.padding/2
8.318 + def layout (self, width):
8.319 + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1,1)
8.320 + ctx = cairo.Context(surface)
8.321 + max_text_height = ctx.text_extents ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcedefghijklmnopqrstuvwxyz0123456789")[3]
8.322 +
8.323 + left_width = 0
8.324 + right_width = 0
8.325 + left_n_lines = 0
8.326 + range_n = 0
8.327 + eventint_n = 0
8.328 + eventstr_n = 0
8.329 + for timeline in self.timelines.get_all ():
8.330 + left_n_lines += 1
8.331 + t_width = ctx.text_extents (timeline.name)[2]
8.332 + left_width = max (left_width, t_width)
8.333 + for rang in timeline.get_ranges ():
8.334 + t_width = ctx.text_extents (rang.name)[2]
8.335 + right_width = max (right_width, t_width)
8.336 + range_n += 1
8.337 + for events_int in timeline.get_events_int ():
8.338 + t_width = ctx.text_extents (events_int.name)[2]
8.339 + right_width = max (right_width, t_width)
8.340 + eventint_n += 1
8.341 + for events_str in timeline.get_events_str ():
8.342 + t_width = ctx.text_extents (events_str.name)[2]
8.343 + right_width = max (right_width, t_width)
8.344 + eventstr_n += 1
8.345 +
8.346 + left_height = left_n_lines * max_text_height + (left_n_lines - 1) * self.padding
8.347 + right_n_lines = range_n + eventint_n + eventstr_n
8.348 + right_height = (right_n_lines - 1) * self.padding + right_n_lines * max_text_height
8.349 + right_data_height = (eventint_n + eventstr_n) * (max_text_height + 5) + range_n * 10
8.350 + right_data_height += (right_n_lines - 1) * self.padding
8.351 +
8.352 + height = max (left_height, right_height)
8.353 + height = max (height, right_data_height)
8.354 +
8.355 + self.left_width = left_width
8.356 + self.right_width = right_width
8.357 + self.max_text_height = max_text_height
8.358 + self.width = width
8.359 + self.height = height + self.padding
8.360 + def draw_line (self, ctx, x, y, width, height):
8.361 + ctx.move_to (x, y)
8.362 + ctx.rel_line_to (width, height)
8.363 + ctx.close_path ()
8.364 + ctx.set_operator (cairo.OPERATOR_SOURCE)
8.365 + ctx.set_line_width (1.0)
8.366 + ctx.set_source_rgb (0,0,0)
8.367 + ctx.stroke ()
8.368 + def draw_events (self, ctx, events, x, y, width, height):
8.369 + if (self.grey_background % 2) == 0:
8.370 + ctx.rectangle (x, y-self.padding/2,
8.371 + width, height+self.padding)
8.372 + ctx.set_source_rgb (0.9,0.9,0.9)
8.373 + ctx.fill ()
8.374 + last_x_drawn = int (x)
8.375 + (lo, hi) = events.get_events_bounds (self.start, self.end)
8.376 + for event in events.events[lo:hi]:
8.377 + real_x = int (x + (event.at - self.start) * width / (self.end - self.start))
8.378 + if real_x > last_x_drawn+2:
8.379 + ctx.rectangle (real_x, y, 1, 1)
8.380 + ctx.set_source_rgb (1,0,0)
8.381 + ctx.stroke ()
8.382 + ctx.move_to (real_x, y+self.max_text_height)
8.383 + ctx.set_source_rgb (0,0,0)
8.384 + ctx.show_text (str (event.value))
8.385 + last_x_drawn = real_x
8.386 + self.grey_background += 1
8.387 + def draw_ranges (self, ctx, ranges, x, y, width, height):
8.388 + if (self.grey_background % 2) == 0:
8.389 + ctx.rectangle (x, y-self.padding/2,
8.390 + width, height+self.padding)
8.391 + ctx.set_source_rgb (0.9,0.9,0.9)
8.392 + ctx.fill ()
8.393 + last_x_drawn = int (x-1)
8.394 + (lo, hi) = ranges.get_ranges_bounds (self.start, self.end)
8.395 + for data_range in ranges.ranges[lo:hi]:
8.396 + s = max (data_range.start, self.start)
8.397 + e = min (data_range.end, self.end)
8.398 + x_start = int (x + (s - self.start) * width / (self.end - self.start))
8.399 + x_end = int (x + (e - self.start) * width / (self.end - self.start))
8.400 + if x_end > last_x_drawn:
8.401 + ctx.rectangle (x_start, y, x_end - x_start, 10)
8.402 + ctx.set_source_rgb (0,0,0)
8.403 + ctx.stroke_preserve ()
8.404 + color = self.colors.lookup (data_range.value)
8.405 + ctx.set_source_rgb (color.r, color.g, color.b)
8.406 + ctx.fill ()
8.407 + last_x_drawn = x_end
8.408 +
8.409 + self.grey_background += 1
8.410 +
8.411 + def draw (self, ctx):
8.412 + timeline_top = 0
8.413 + top_y = self.padding / 2
8.414 + left_x_start = self.padding / 2
8.415 + left_x_end = left_x_start + self.left_width
8.416 + right_x_start = left_x_end + self.padding
8.417 + right_x_end = right_x_start + self.right_width
8.418 + data_x_start = right_x_end + self.padding /2
8.419 + data_x_end = self.width
8.420 + data_width = data_x_end - data_x_start
8.421 + cur_y = top_y
8.422 + self.draw_line (ctx, 0, 0, self.width, 0)
8.423 + self.grey_background = 1
8.424 + for timeline in self.timelines.get_all ():
8.425 + (y_bearing,t_width,t_height) = ctx.text_extents (timeline.name)[1:4]
8.426 + ctx.move_to (left_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
8.427 + ctx.show_text (timeline.name);
8.428 + for events_int in timeline.get_events_int ():
8.429 + (y_bearing, t_width, t_height) = ctx.text_extents (events_int.name)[1:4]
8.430 + ctx.move_to (right_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
8.431 + ctx.show_text (events_int.name)
8.432 + self.draw_events (ctx, events_int, data_x_start, cur_y, data_width, self.max_text_height+5)
8.433 + cur_y += self.max_text_height + 5 + self.padding
8.434 + self.draw_line (ctx, right_x_start-self.padding/2, cur_y - self.padding / 2,
8.435 + self.right_width + self.padding, 0)
8.436 +
8.437 + for events_str in timeline.get_events_str ():
8.438 + (y_bearing, t_width, t_height) = ctx.text_extents (events_str.name)[1:4]
8.439 + ctx.move_to (right_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
8.440 + ctx.show_text (events_str.name)
8.441 + self.draw_events (ctx, events_str, data_x_start, cur_y, data_width, self.max_text_height+5)
8.442 + cur_y += self.max_text_height + 5 + self.padding
8.443 + self.draw_line (ctx, right_x_start-self.padding/2, cur_y - self.padding / 2,
8.444 + self.right_width + self.padding, 0)
8.445 + for ranges in timeline.get_ranges ():
8.446 + (y_bearing, t_width, t_height) = ctx.text_extents (ranges.name)[1:4]
8.447 + ctx.move_to (right_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
8.448 + ctx.show_text (ranges.name)
8.449 + self.draw_ranges (ctx, ranges, data_x_start, cur_y, data_width, 10)
8.450 + cur_y += self.max_text_height + self.padding
8.451 + self.draw_line (ctx, right_x_start-self.padding/2, cur_y - self.padding / 2,
8.452 + self.right_width + self.padding, 0)
8.453 + self.draw_line (ctx, 0, cur_y - self.padding / 2,
8.454 + self.width, 0)
8.455 + bot_y = cur_y - self.padding / 2
8.456 + self.draw_line (ctx, left_x_end+self.padding/2, 0,
8.457 + 0, bot_y)
8.458 + self.draw_line (ctx, right_x_end+self.padding/2, 0,
8.459 + 0, bot_y)
8.460 + return
8.461 +
8.462 +class ScaleRenderer:
8.463 + def __init__ (self):
8.464 + self.__top = 0
8.465 + return
8.466 + def set_bounds (self, lo, hi):
8.467 + self.__lo = lo
8.468 + self.__hi = hi
8.469 + def get_position (self, x):
8.470 + real_x = (x - self.__lo ) * self.__width / (self.__hi - self.__lo)
8.471 + return real_x
8.472 + def set_top (self):
8.473 + self.__top = 1
8.474 + def set_bot (self):
8.475 + self.__top = 0
8.476 + def layout (self, width):
8.477 + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1,1)
8.478 + ctx = cairo.Context(surface)
8.479 +
8.480 + # calculate scale delta
8.481 + data_delta = self.__hi - self.__lo
8.482 + closest = 1
8.483 + while (closest*10) < data_delta:
8.484 + closest *= 10
8.485 + if (data_delta / closest) == 0:
8.486 + delta = closest
8.487 + elif (data_delta / closest) == 1:
8.488 + delta = closest / 10
8.489 + else:
8.490 + delta = closest
8.491 + start = self.__lo - (self.__lo % delta) + delta
8.492 + end = self.__hi - (self.__hi % delta)
8.493 +
8.494 + self.__delta = delta
8.495 + self.__width = width
8.496 +
8.497 + # calculate text height
8.498 + max_text_height = ctx.text_extents ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcedefghijklmnopqrstuvwxyz0123456789")[3]
8.499 + self.max_text_height = max_text_height
8.500 + height = max_text_height + 10
8.501 + self.__height = height
8.502 +
8.503 + def get_height (self):
8.504 + return self.__height
8.505 + def draw (self, ctx):
8.506 + delta = self.__delta
8.507 + start = self.__lo - (self.__lo % delta) + delta
8.508 + end = self.__hi - (self.__hi % delta)
8.509 +
8.510 + if self.__top == 1:
8.511 + s = -1
8.512 + else:
8.513 + s = 1
8.514 + # print scale points
8.515 + ctx.set_source_rgb (0, 0, 0)
8.516 + ctx.set_line_width (1.0)
8.517 + ticks = range (int (start), int (end + delta), int (delta))
8.518 + for x in ticks:
8.519 + real_x = (x - self.__lo ) * self.__width / (self.__hi - self.__lo)
8.520 + ctx.move_to (real_x, 0)
8.521 + ctx.line_to (real_x, 5*s)
8.522 + ctx.close_path ()
8.523 + ctx.stroke ()
8.524 + (t_y_bearing, t_width, t_height) = ctx.text_extents (str (x))[1:4]
8.525 + if self.__top:
8.526 + text_delta = t_height + t_y_bearing
8.527 + else:
8.528 + text_delta = -t_y_bearing
8.529 + ctx.move_to (real_x - t_width/2, (5 + 5 + text_delta)*s)
8.530 + ctx.show_text (str (x))
8.531 + # draw subticks
8.532 + delta /= 10
8.533 + if delta > 0:
8.534 + start = self.__lo - (self.__lo % delta) + delta
8.535 + end = self.__hi - (self.__hi % delta)
8.536 + for x in range (int (start), int (end + delta), int (delta)):
8.537 + real_x = (x - self.__lo ) * self.__width / (self.__hi - self.__lo)
8.538 + ctx.move_to (real_x, 0)
8.539 + ctx.line_to (real_x, 3*s)
8.540 + ctx.close_path ()
8.541 + ctx.stroke ()
8.542 +
8.543 +
8.544 +
8.545 +class GraphicRenderer:
8.546 + def __init__(self, start, end):
8.547 + self.__start = float (start)
8.548 + self.__end = float (end)
8.549 + self.__mid_scale = ScaleRenderer ()
8.550 + self.__mid_scale.set_top ()
8.551 + self.__bot_scale = ScaleRenderer ()
8.552 + self.__bot_scale.set_bounds (start, end)
8.553 + self.__bot_scale.set_bot ()
8.554 + self.__width = 1
8.555 + self.__height = 1
8.556 + def get_width (self):
8.557 + return self.__width
8.558 + def get_height (self):
8.559 + return self.__height
8.560 + # return x, y, width, height
8.561 + def get_data_rectangle (self):
8.562 + y_start = self.__top_legend.get_height ()
8.563 + x_start = self.__data.get_data_x_start ()
8.564 + return (x_start, y_start, self.__width - x_start, self.__data.get_height ())
8.565 + def scale_data (self, x):
8.566 + x_start = self.__data.get_data_x_start ()
8.567 + x_scaled = x / (self.__width - x_start) * (self.__r_end - self.__r_start)
8.568 + return x_scaled
8.569 + # return x, y, width, height
8.570 + def get_selection_rectangle (self):
8.571 + y_start = self.__top_legend.get_height () + self.__data.get_height () + self.__mid_scale.get_height () + 20
8.572 + y_height = self.__bot_scale.get_height () + 20
8.573 + x_start = self.__bot_scale.get_position (self.__r_start)
8.574 + x_end = self.__bot_scale.get_position (self.__r_end)
8.575 + return (x_start,y_start,x_end-x_start,y_height)
8.576 + def scale_selection (self, x):
8.577 + x_scaled = x / self.__width * (self.__end - self.__start)
8.578 + return x_scaled
8.579 + def set_range (self,start, end):
8.580 + s = min (start, end)
8.581 + e = max (start, end)
8.582 + start = max (self.__start, s)
8.583 + end = min (self.__end, e)
8.584 + self.__r_start = start
8.585 + self.__r_end = end
8.586 + self.__data.set_render_range (start, end)
8.587 + self.__mid_scale.set_bounds (start, end)
8.588 + self.layout (self.__width, self.__height)
8.589 + def get_range (self):
8.590 + return (self.__r_start, self.__r_end)
8.591 + def set_data (self, data):
8.592 + self.__data = data
8.593 + def set_top_legend (self, top_legend):
8.594 + self.__top_legend = top_legend
8.595 + def layout (self, width, height):
8.596 + self.__width = width
8.597 + self.__height = height
8.598 + self.__top_legend.layout (width)
8.599 + top_legend_height = self.__top_legend.get_height ()
8.600 + self.__data.layout (width)
8.601 + self.__mid_scale.layout (width - self.__data.get_data_x_start ())
8.602 + self.__bot_scale.layout (width)
8.603 + return
8.604 + def __x_pixel (self, x, width):
8.605 + new_x = (x - self.__start) * width / (self.__end - self.__start)
8.606 + return new_x
8.607 +
8.608 + def draw (self, ctx):
8.609 + # default background is white
8.610 + ctx.save ()
8.611 + ctx.set_source_rgb (1, 1, 1)
8.612 + ctx.set_operator (cairo.OPERATOR_SOURCE)
8.613 + ctx.rectangle (0,0,self.__width,self.__height)
8.614 + ctx.fill ()
8.615 +
8.616 + # top legend
8.617 + ctx.save ()
8.618 + self.__top_legend.draw (ctx)
8.619 + top_legend_height = self.__top_legend.get_height ()
8.620 + ctx.restore ()
8.621 +
8.622 + # separation line
8.623 + ctx.move_to (0, top_legend_height)
8.624 + ctx.line_to (self.__width, top_legend_height)
8.625 + ctx.close_path ()
8.626 + ctx.set_line_width (2)
8.627 + ctx.set_source_rgb (0,0,0)
8.628 + ctx.stroke ()
8.629 +
8.630 + # data
8.631 + ctx.save ()
8.632 + ctx.translate (0,
8.633 + top_legend_height)
8.634 + self.__data.draw (ctx)
8.635 + ctx.restore ()
8.636 +
8.637 + # scale below data
8.638 + ctx.save ()
8.639 + ctx.translate (self.__data.get_data_x_start (),
8.640 + top_legend_height + self.__data.get_height () + self.__mid_scale.get_height ())
8.641 + self.__mid_scale.draw (ctx)
8.642 + ctx.restore ()
8.643 +
8.644 + height_used = top_legend_height + self.__data.get_height () + self.__mid_scale.get_height ()
8.645 +
8.646 + # separation between scale and left pane
8.647 + ctx.move_to (self.__data.get_data_x_start (), height_used)
8.648 + ctx.rel_line_to (0, -self.__mid_scale.get_height ())
8.649 + ctx.close_path ()
8.650 + ctx.set_source_rgb (0,0,0)
8.651 + ctx.set_line_width (2)
8.652 + ctx.stroke ()
8.653 +
8.654 + # separation below scale
8.655 + ctx.move_to (0, height_used)
8.656 + ctx.line_to (self.__width, height_used)
8.657 + ctx.close_path ()
8.658 + ctx.set_line_width (2)
8.659 + ctx.set_source_rgb (0,0,0)
8.660 + ctx.stroke ()
8.661 +
8.662 + select_start = self.__bot_scale.get_position (self.__r_start)
8.663 + select_end = self.__bot_scale.get_position (self.__r_end)
8.664 +
8.665 + # left connection between top scale and bottom scale
8.666 + ctx.move_to (0, height_used);
8.667 + ctx.line_to (self.__data.get_data_x_start (), height_used)
8.668 + ctx.line_to (select_start, height_used + 20)
8.669 + ctx.line_to (0, height_used + 20)
8.670 + ctx.line_to (0,height_used)
8.671 + ctx.set_source_rgb (0,0,0)
8.672 + ctx.set_line_width (1)
8.673 + ctx.stroke_preserve ()
8.674 + ctx.set_source_rgb (0.9,0.9,0.9)
8.675 + ctx.fill ()
8.676 +
8.677 + # right connection between top scale and bottom scale
8.678 + ctx.move_to (self.__width, height_used)
8.679 + ctx.line_to (self.__width, height_used+20)
8.680 + ctx.line_to (select_end, height_used+20)
8.681 + ctx.line_to (self.__width, height_used)
8.682 + ctx.set_source_rgb (0,0,0)
8.683 + ctx.set_line_width (1)
8.684 + ctx.stroke_preserve ()
8.685 + ctx.set_source_rgb (0.9,0.9,0.9)
8.686 + ctx.fill ()
8.687 +
8.688 + height_used += 20
8.689 +
8.690 + # unused area background
8.691 + unused_start = self.__bot_scale.get_position (self.__r_start)
8.692 + unused_end = self.__bot_scale.get_position (self.__r_end)
8.693 + unused_height = self.__bot_scale.get_height () + 20
8.694 + ctx.rectangle (0, height_used,
8.695 + unused_start,
8.696 + unused_height)
8.697 + ctx.rectangle (unused_end,
8.698 + height_used,
8.699 + self.__width - unused_end,
8.700 + unused_height)
8.701 + ctx.set_source_rgb (0.9,0.9,0.9)
8.702 + ctx.fill ()
8.703 +
8.704 + # border line around bottom scale
8.705 + ctx.move_to (unused_end, height_used)
8.706 + ctx.line_to (self.__width, height_used)
8.707 + ctx.line_to (self.__width, height_used + unused_height)
8.708 + ctx.line_to (0, height_used + unused_height)
8.709 + ctx.line_to (0, height_used)
8.710 + ctx.line_to (unused_start, height_used)
8.711 + ctx.close_path ()
8.712 + ctx.set_line_width (2)
8.713 + ctx.set_source_rgb (0,0,0)
8.714 + ctx.stroke ()
8.715 + ctx.move_to (unused_start, height_used)
8.716 + ctx.line_to (unused_end, height_used)
8.717 + ctx.close_path ()
8.718 + ctx.set_line_width (1)
8.719 + ctx.set_source_rgb (0.9,0.9,0.9)
8.720 + ctx.stroke ()
8.721 +
8.722 + # unused area dot borders
8.723 + ctx.save ()
8.724 + ctx.move_to (max (unused_start, 2), height_used)
8.725 + ctx.rel_line_to (0,unused_height)
8.726 + ctx.move_to (min (unused_end, self.__width-2), height_used)
8.727 + ctx.rel_line_to (0, unused_height)
8.728 + ctx.set_dash ([5], 0)
8.729 + ctx.set_source_rgb (0,0,0)
8.730 + ctx.set_line_width (1)
8.731 + ctx.stroke ()
8.732 + ctx.restore ()
8.733 +
8.734 + # bottom scale
8.735 + ctx.save ()
8.736 + ctx.translate (0, height_used)
8.737 + self.__bot_scale.draw (ctx)
8.738 + ctx.restore ()
8.739 +
8.740 +class GtkGraphicRenderer (gtk.DrawingArea):
8.741 + def __init__ (self, data):
8.742 + super (GtkGraphicRenderer, self).__init__ ()
8.743 + self.__data = data
8.744 + self.__moving_left = False
8.745 + self.__moving_right = False
8.746 + self.__moving_both = False
8.747 + self.__moving_top = False
8.748 + self.__force_full_redraw = True
8.749 + self.add_events (gtk.gdk.POINTER_MOTION_MASK)
8.750 + self.add_events (gtk.gdk.BUTTON_PRESS_MASK)
8.751 + self.add_events (gtk.gdk.BUTTON_RELEASE_MASK)
8.752 + self.connect ("expose_event", self.expose)
8.753 + self.connect ('size-allocate', self.size_allocate)
8.754 + self.connect ('motion-notify-event', self.motion_notify)
8.755 + self.connect ('button-press-event', self.button_press)
8.756 + self.connect ('button-release-event', self.button_release)
8.757 + def set_smaller_zoom (self):
8.758 + (start, end) = self.__data.get_range ()
8.759 + self.__data.set_range (start, start+(end-start)*2)
8.760 + self.__force_full_redraw = True
8.761 + self.queue_draw ()
8.762 + def set_bigger_zoom (self):
8.763 + (start, end) = self.__data.get_range ()
8.764 + self.__data.set_range (start, start+(end-start)/2)
8.765 + self.__force_full_redraw = True
8.766 + self.queue_draw ()
8.767 + def output_png (self, filename):
8.768 + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
8.769 + self.__data.get_width (),
8.770 + self.__data.get_height ())
8.771 + ctx = cairo.Context (self.__buffer_surface)
8.772 + self.__data.draw (ctx)
8.773 + surface.write_to_png (filename)
8.774 + def button_press (self, widget, event):
8.775 + (x, y, width, height) = self.__data.get_selection_rectangle ()
8.776 + (d_x, d_y, d_width, d_height) = self.__data.get_data_rectangle ()
8.777 + if event.y > y and event.y < y+height:
8.778 + if abs (event.x - x) < 5:
8.779 + self.__moving_left = True
8.780 + return True
8.781 + if abs (event.x - (x+width)) < 5:
8.782 + self.__moving_right = True
8.783 + return True
8.784 + if event.x > x and event.x < x+width:
8.785 + self.__moving_both = True
8.786 + self.__moving_both_start = event.x
8.787 + self.__moving_both_cur = event.x
8.788 + return True
8.789 + if event.y > d_y and event.y < (d_y + d_height):
8.790 + if event.x > d_x and event.x < (d_x + d_width):
8.791 + self.__moving_top = True
8.792 + self.__moving_top_start = event.x
8.793 + self.__moving_top_cur = event.x
8.794 + return True
8.795 + return False
8.796 + def button_release (self, widget, event):
8.797 + if self.__moving_left:
8.798 + self.__moving_left = False
8.799 + left = self.__data.scale_selection (self.__moving_left_cur)
8.800 + right = self.__data.get_range ()[1]
8.801 + self.__data.set_range (left, right)
8.802 + self.__force_full_redraw = True
8.803 + self.queue_draw ()
8.804 + return True
8.805 + if self.__moving_right:
8.806 + self.__moving_right = False
8.807 + right = self.__data.scale_selection (self.__moving_right_cur)
8.808 + left = self.__data.get_range ()[0]
8.809 + self.__data.set_range (left, right)
8.810 + self.__force_full_redraw = True
8.811 + self.queue_draw ()
8.812 + return True
8.813 + if self.__moving_both:
8.814 + self.__moving_both = False
8.815 + delta = self.__data.scale_selection (self.__moving_both_cur - self.__moving_both_start)
8.816 + (left, right) = self.__data.get_range ()
8.817 + self.__data.set_range (left+delta, right+delta)
8.818 + self.__force_full_redraw = True
8.819 + self.queue_draw ()
8.820 + return True
8.821 + if self.__moving_top:
8.822 + self.__moving_top = False
8.823 + return False
8.824 + def motion_notify (self, widget, event):
8.825 + (x, y, width, height) = self.__data.get_selection_rectangle ()
8.826 + if self.__moving_left:
8.827 + if event.x <= 0:
8.828 + self.__moving_left_cur = 0
8.829 + elif event.x >= x+width:
8.830 + self.__moving_left_cur = x+width
8.831 + else:
8.832 + self.__moving_left_cur = event.x
8.833 + self.queue_draw_area (0, int(y), int(self.__width), int(height))
8.834 + return True
8.835 + if self.__moving_right:
8.836 + if event.x >= self.__width:
8.837 + self.__moving_right = self.__width
8.838 + elif event.x < x:
8.839 + self.__moving_right_cur = x
8.840 + else:
8.841 + self.__moving_right_cur = event.x
8.842 + self.queue_draw_area (0, int(y), int(self.__width), int(height))
8.843 + return True
8.844 + if self.__moving_both:
8.845 + cur_e = self.__width - (x + width - self.__moving_both_start)
8.846 + cur_s = (self.__moving_both_start - x)
8.847 + if event.x < cur_s:
8.848 + self.__moving_both_cur = cur_s
8.849 + elif event.x > cur_e:
8.850 + self.__moving_both_cur = cur_e
8.851 + else:
8.852 + self.__moving_both_cur = event.x
8.853 + self.queue_draw_area (0, int(y), int(self.__width), int(height))
8.854 + return True
8.855 + if self.__moving_top:
8.856 + self.__moving_top_cur = event.x
8.857 + delta = self.__data.scale_data (self.__moving_top_start-self.__moving_top_cur)
8.858 + (left, right) = self.__data.get_range ()
8.859 + self.__data.set_range (left+delta, right+delta)
8.860 + self.__force_full_redraw = True
8.861 + self.__moving_top_start = event.x
8.862 + self.queue_draw ()
8.863 + return True
8.864 + (d_x, d_y, d_width, d_height) = self.__data.get_data_rectangle ()
8.865 + if event.y > y and event.y < y+height:
8.866 + if abs (event.x - x) < 5 or abs (event.x - (x+width)) < 5:
8.867 + widget.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.SB_H_DOUBLE_ARROW))
8.868 + return True
8.869 + if event.x > x and event.x < x+width:
8.870 + widget.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.FLEUR))
8.871 + return True
8.872 + if event.y > d_y and event.y < (d_y + d_height):
8.873 + if event.x > d_x and event.x < (d_x + d_width):
8.874 + widget.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.FLEUR))
8.875 + return True
8.876 + widget.window.set_cursor (None)
8.877 + return False
8.878 + def size_allocate (self, widget, allocation):
8.879 + self.__width = allocation.width
8.880 + self.__height = allocation.height
8.881 + self.__data.layout (allocation.width, allocation.height)
8.882 + self.__force_full_redraw = True
8.883 + self.queue_draw ()
8.884 + def expose (self, widget, event):
8.885 + if self.__force_full_redraw:
8.886 + self.__buffer_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
8.887 + self.__data.get_width (),
8.888 + self.__data.get_height ())
8.889 + ctx = cairo.Context(self.__buffer_surface)
8.890 + self.__data.draw (ctx)
8.891 + self.__force_full_redraw = False
8.892 + ctx = widget.window.cairo_create()
8.893 + ctx.rectangle(event.area.x, event.area.y,
8.894 + event.area.width, event.area.height)
8.895 + ctx.clip()
8.896 + ctx.set_source_surface (self.__buffer_surface)
8.897 + ctx.paint ()
8.898 + (x, y, width, height) = self.__data.get_selection_rectangle ()
8.899 + if self.__moving_left:
8.900 + ctx.move_to (max (self.__moving_left_cur, 2), y)
8.901 + ctx.rel_line_to (0, height)
8.902 + ctx.close_path ()
8.903 + ctx.set_line_width (1)
8.904 + ctx.set_source_rgb (0,0,0)
8.905 + ctx.stroke ()
8.906 + if self.__moving_right:
8.907 + ctx.move_to (min (self.__moving_right_cur, self.__width-2), y)
8.908 + ctx.rel_line_to (0, height)
8.909 + ctx.close_path ()
8.910 + ctx.set_line_width (1)
8.911 + ctx.set_source_rgb (0,0,0)
8.912 + ctx.stroke ()
8.913 + if self.__moving_both:
8.914 + delta_x = self.__moving_both_cur - self.__moving_both_start
8.915 + left_x = x + delta_x
8.916 + ctx.move_to (x+delta_x, y)
8.917 + ctx.rel_line_to (0, height)
8.918 + ctx.close_path ()
8.919 + ctx.move_to (x+width+delta_x, y)
8.920 + ctx.rel_line_to (0, height)
8.921 + ctx.close_path ()
8.922 + ctx.set_source_rgb (0,0,0)
8.923 + ctx.set_line_width (1)
8.924 + ctx.stroke ()
8.925 + return False
8.926 +
8.927 +class MainWindow:
8.928 + def __init__ (self):
8.929 + return
8.930 + def run (self, graphic):
8.931 + window = gtk.Window()
8.932 + self.__window = window
8.933 + window.set_default_size (200, 200)
8.934 + vbox = gtk.VBox ()
8.935 + window.add (vbox)
8.936 + render = GtkGraphicRenderer(graphic)
8.937 + self.__render = render
8.938 + vbox.pack_end (render, True, True, 0)
8.939 + hbox = gtk.HBox ()
8.940 + vbox.pack_start (hbox, False, False, 0)
8.941 + smaller_zoom = gtk.Button ("Zoom Out")
8.942 + smaller_zoom.connect ("clicked", self.__set_smaller_cb)
8.943 + hbox.pack_start (smaller_zoom)
8.944 + bigger_zoom = gtk.Button ("Zoom In")
8.945 + bigger_zoom.connect ("clicked", self.__set_bigger_cb)
8.946 + hbox.pack_start (bigger_zoom)
8.947 + output_png = gtk.Button ("Output Png")
8.948 + output_png.connect ("clicked", self.__output_png_cb)
8.949 + hbox.pack_start (output_png)
8.950 + window.connect('destroy', gtk.main_quit)
8.951 + window.show_all()
8.952 + #gtk.bindings_activate (gtk.main_quit, 'q', 0)
8.953 + gtk.main()
8.954 + def __set_smaller_cb (self, widget):
8.955 + self.__render.set_smaller_zoom ()
8.956 + def __set_bigger_cb (self, widget):
8.957 + self.__render.set_bigger_zoom ()
8.958 + def __output_png_cb (self, widget):
8.959 + dialog = gtk.FileChooserDialog ("Output Png", self.__window,
8.960 + gtk.FILE_CHOOSER_ACTION_SAVE, ("Save",1))
8.961 + self.__dialog = dialog
8.962 + dialog.set_default_response (1)
8.963 + dialog.connect ("response", self.__dialog_response_cb)
8.964 + dialog.show ()
8.965 + return
8.966 + def __dialog_response_cb (self, widget, response):
8.967 + if response == 1:
8.968 + filename = self.__dialog.get_filename ()
8.969 + self.__render.output_png (filename)
8.970 + widget.hide ()
8.971 + return
8.972 +
8.973 +
8.974 +
8.975 +def read_data(filename):
8.976 + timelines = Timelines ()
8.977 + colors = Colors ()
8.978 + fh = open(filename)
8.979 + m1 = re.compile ('range ([^ ]+) ([^ ]+) ([^ ]+) ([0-9]+) ([0-9]+)')
8.980 + m2 = re.compile ('event-str ([^ ]+) ([^ ]+) ([^ ]+) ([0-9]+)')
8.981 + m3 = re.compile ('event-int ([^ ]+) ([^ ]+) ([0-9]+) ([0-9]+)')
8.982 + m4 = re.compile ('color ([^ ]+) #([a-fA-F0-9]{2,2})([a-fA-F0-9]{2,2})([a-fA-F0-9]{2,2})')
8.983 + for line in fh.readlines():
8.984 + m = m1.match (line)
8.985 + if m:
8.986 + line_name = m.group (1)
8.987 + timeline = timelines.get (m.group (1))
8.988 + rang = timeline.get_range (m.group (2))
8.989 + data_range = DataRange ()
8.990 + data_range.value = m.group (3)
8.991 + data_range.start = int (m.group (4))
8.992 + data_range.end = int (m.group (5))
8.993 + rang.add_range (data_range)
8.994 + continue
8.995 + m = m2.match (line)
8.996 + if m:
8.997 + line_name = m.group (1)
8.998 + timeline = timelines.get (m.group (1))
8.999 + ev = timeline.get_event_str (m.group (2))
8.1000 + event = EventString ()
8.1001 + event.value = m.group (3)
8.1002 + event.at = int (m.group (4))
8.1003 + ev.add_event (event)
8.1004 + continue
8.1005 + m = m3.match (line)
8.1006 + if m:
8.1007 + line_name = m.group (1)
8.1008 + timeline = timelines.get (m.group (1))
8.1009 + ev = timeline.get_event_int (m.group (2))
8.1010 + event = EventInt ()
8.1011 + event.value = int (m.group (3))
8.1012 + event.at = int (m.group (4))
8.1013 + ev.add_event (event)
8.1014 + continue
8.1015 +
8.1016 + m = m4.match (line)
8.1017 + if m:
8.1018 + r = int (m.group (2), 16)
8.1019 + g = int (m.group (3), 16)
8.1020 + b = int (m.group (4), 16)
8.1021 + color = Color (r/255, g/255, b/255)
8.1022 + colors.add (m.group (1), color)
8.1023 + continue
8.1024 + timelines.sort ()
8.1025 + return (colors, timelines)
8.1026 +
8.1027 +
8.1028 +
8.1029 +def main():
8.1030 + (colors, timelines) = read_data (sys.argv[1])
8.1031 + (lower_bound, upper_bound) = timelines.get_bounds ()
8.1032 + graphic = GraphicRenderer (lower_bound, upper_bound)
8.1033 + top_legend = TopLegendRenderer ()
8.1034 + range_values = timelines.get_all_range_values ()
8.1035 + range_colors = []
8.1036 + for range_value in range_values:
8.1037 + range_colors.append (colors.lookup (range_value))
8.1038 + top_legend.set_legends (range_values,
8.1039 + range_colors)
8.1040 + graphic.set_top_legend (top_legend)
8.1041 + data = TimelinesRenderer ()
8.1042 + data.set_timelines (timelines, colors)
8.1043 + graphic.set_data (data)
8.1044 +
8.1045 + # default range
8.1046 + range_mid = (upper_bound - lower_bound) /2
8.1047 + range_width = (upper_bound - lower_bound) /10
8.1048 + range_lo = range_mid - range_width / 2
8.1049 + range_hi = range_mid + range_width / 2
8.1050 + graphic.set_range (range_lo, range_hi)
8.1051 +
8.1052 + main_window = MainWindow ()
8.1053 + main_window.run (graphic)
8.1054 +
8.1055 +
8.1056 +main ()
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/utils/replay-simulation.cc Tue Aug 29 17:47:17 2006 +0200
9.3 @@ -0,0 +1,265 @@
9.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
9.5 +/*
9.6 + * Copyright (c) 2006 INRIA
9.7 + * All rights reserved.
9.8 + *
9.9 + * This program is free software; you can redistribute it and/or modify
9.10 + * it under the terms of the GNU General Public License version 2 as
9.11 + * published by the Free Software Foundation;
9.12 + *
9.13 + * This program is distributed in the hope that it will be useful,
9.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.16 + * GNU General Public License for more details.
9.17 + *
9.18 + * You should have received a copy of the GNU General Public License
9.19 + * along with this program; if not, write to the Free Software
9.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9.21 + *
9.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
9.23 + */
9.24 +
9.25 +#include "yans/simulator.h"
9.26 +#include "yans/event.h"
9.27 +#include "yans/event.tcc"
9.28 +#include "yans/wall-clock-ms.h"
9.29 +#include <vector>
9.30 +#include <deque>
9.31 +#include <fstream>
9.32 +#include <iostream>
9.33 +
9.34 +using namespace yans;
9.35 +
9.36 +class LogReader {
9.37 +public:
9.38 + void read_from_filename (char const *filename);
9.39 + void run (void);
9.40 + void print_stats (void);
9.41 +private:
9.42 + struct Command {
9.43 + enum {
9.44 + REMOVE,
9.45 + INSERT,
9.46 + INSERT_LATER,
9.47 + INSERT_REMOVE
9.48 + } m_type;
9.49 + // uid at which this command is supposed to be executed.
9.50 + uint32_t m_uid;
9.51 + union {
9.52 + struct {
9.53 + // time at which the event is supposed to expire
9.54 + uint64_t m_ev_us;
9.55 + } insert;
9.56 + struct {
9.57 + // location in the array of events to remove where
9.58 + // to insert this event once it is inserted in
9.59 + // the scheduler.
9.60 + uint32_t m_ev_loc;
9.61 + // time at which the event is supposed to expire
9.62 + uint64_t m_ev_us;
9.63 + } insert_remove;
9.64 + };
9.65 + };
9.66 + void execute_log_commands (uint32_t uid);
9.67 +
9.68 + typedef std::deque<struct Command> Commands;
9.69 + typedef std::deque<struct Command>::iterator CommandsI;
9.70 + typedef std::deque<Event > RemoveEvents;
9.71 +
9.72 +
9.73 + Commands m_commands;
9.74 + CommandsI m_command;
9.75 + RemoveEvents m_remove_events;
9.76 + uint32_t m_uid;
9.77 +};
9.78 +
9.79 +typedef std::vector<std::pair<uint32_t, uint32_t> > Removes;
9.80 +typedef std::vector<std::pair<uint32_t, uint32_t> >::iterator RemovesI;
9.81 +
9.82 +void
9.83 +LogReader::read_from_filename (char const *filename)
9.84 +{
9.85 + std::ifstream log;
9.86 + std::cout << "read log..." << std::endl;
9.87 + Removes removes;
9.88 + log.open (filename);
9.89 + while (!log.eof ()) {
9.90 + std::string type;
9.91 + log >> type;
9.92 + if (type == "i") {
9.93 + uint32_t now_uid, ev_uid;
9.94 + uint64_t now_us, ev_us;
9.95 + log >> now_uid >> now_us >> ev_uid >> ev_us;
9.96 + struct Command cmd;
9.97 + cmd.m_type = Command::INSERT;
9.98 + cmd.m_uid = now_uid;
9.99 + cmd.insert.m_ev_us = ev_us;
9.100 + m_commands.push_back (cmd);
9.101 + } else if (type == "r") {
9.102 + uint32_t now_uid, ev_uid;
9.103 + uint64_t now_us, ev_us;
9.104 + log >> now_uid >> now_us >> ev_uid >> ev_us;
9.105 + struct Command cmd;
9.106 + cmd.m_type = Command::REMOVE;
9.107 + cmd.m_uid = now_uid;
9.108 + m_commands.push_back (cmd);
9.109 + removes.push_back (std::make_pair (now_uid, ev_uid));
9.110 + } else if (type == "il") {
9.111 + uint32_t now_uid, ev_uid;
9.112 + uint64_t now_us, ev_us;
9.113 + log >> now_uid >> now_us >> ev_uid >> ev_us;
9.114 + struct Command cmd;
9.115 + cmd.m_type = Command::INSERT_LATER;
9.116 + cmd.m_uid = now_uid;
9.117 + m_commands.push_back (cmd);
9.118 + }
9.119 + }
9.120 + log.close ();
9.121 +
9.122 + std::cout << "gather insert removes..." << std::endl;
9.123 + for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) {
9.124 + if (i->m_type == Command::INSERT) {
9.125 + for (RemovesI j = removes.begin (); j != removes.end (); j++) {
9.126 + if (j->second == i->m_uid) {
9.127 + // this insert will be removed later.
9.128 + uint64_t us = i->insert.m_ev_us;
9.129 + uint32_t uid = i->m_uid;
9.130 + i->m_type = Command::INSERT_REMOVE;
9.131 + i->m_uid = uid;
9.132 + i->insert_remove.m_ev_us = us;
9.133 + i->insert_remove.m_ev_loc = j->first;
9.134 + break;
9.135 + }
9.136 + }
9.137 + }
9.138 + }
9.139 + std::cout << "calculate remove locations..." << std::endl;
9.140 + // calculate the final insert/remove location.
9.141 + for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) {
9.142 + if (i->m_type == Command::INSERT_REMOVE) {
9.143 + uint32_t loc = 0;
9.144 + for (CommandsI tmp = i; tmp != m_commands.end (); tmp++) {
9.145 + if (tmp->m_type == Command::REMOVE &&
9.146 + tmp->m_uid == i->insert_remove.m_ev_loc) {
9.147 + i->insert_remove.m_ev_loc = loc;
9.148 + break;
9.149 + }
9.150 + loc++;
9.151 + }
9.152 + }
9.153 + }
9.154 +}
9.155 +void
9.156 +LogReader::execute_log_commands (uint32_t uid)
9.157 +{
9.158 + if (m_command == m_commands.end ()) {
9.159 + return;
9.160 + }
9.161 + //std::cout << "one event, uid=" <<m_uid<< std::endl;
9.162 + struct Command cmd = *m_command;
9.163 + //std::cout << "cmd uid=" <<cmd.m_uid<< std::endl;
9.164 + while (cmd.m_uid == uid) {
9.165 + m_command++;
9.166 + switch (cmd.m_type) {
9.167 + case Command::INSERT:
9.168 + //std::cout << "exec insert now=" << Simulator::now_us ()
9.169 + //<< ", time=" << cmd.insert.m_ev_us << std::endl;
9.170 + Simulator::schedule_abs_us (cmd.insert.m_ev_us,
9.171 + make_event (&LogReader::execute_log_commands, this, m_uid));
9.172 + m_uid++;
9.173 + break;
9.174 + case Command::INSERT_LATER:
9.175 + //std::cout << "exec insert later" << std::endl;
9.176 + Simulator::schedule_now (make_event (&LogReader::execute_log_commands, this, m_uid));
9.177 + m_uid++;
9.178 + break;
9.179 + case Command::REMOVE: {
9.180 + //std::cout << "exec remove" << std::endl;
9.181 + Event ev = m_remove_events.front ();
9.182 + m_remove_events.pop_front ();
9.183 + Simulator::remove (ev);
9.184 + } break;
9.185 + case Command::INSERT_REMOVE: {
9.186 + //std::cout << "exec insert remove" << std::endl;
9.187 + Event ev = make_event (&LogReader::execute_log_commands, this, m_uid);
9.188 + Simulator::schedule_abs_us (cmd.insert_remove.m_ev_us, ev);
9.189 + m_remove_events[cmd.insert_remove.m_ev_loc] = ev;
9.190 + m_uid++;
9.191 + } break;
9.192 + }
9.193 + cmd = *m_command;
9.194 + }
9.195 +}
9.196 +
9.197 +void
9.198 +LogReader::print_stats (void)
9.199 +{
9.200 + uint32_t n_inserts = 0;
9.201 + uint32_t n_removes = 0;
9.202 + for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) {
9.203 + switch (i->m_type) {
9.204 + case Command::INSERT:
9.205 + n_inserts++;
9.206 + break;
9.207 + case Command::INSERT_LATER:
9.208 + n_inserts++;
9.209 + break;
9.210 + case Command::INSERT_REMOVE:
9.211 + n_inserts++;
9.212 + break;
9.213 + case Command::REMOVE:
9.214 + n_removes++;
9.215 + break;
9.216 + }
9.217 + }
9.218 + std::cout << "inserts="<<n_inserts<<", removes="<<n_removes<<std::endl;
9.219 + std::cout << "run simulation..."<<std::endl;
9.220 +}
9.221 +
9.222 +void
9.223 +LogReader::run (void)
9.224 +{
9.225 + m_uid = 0;
9.226 + WallClockMs time;
9.227 + time.start ();
9.228 + m_command = m_commands.begin ();
9.229 + execute_log_commands (m_uid);
9.230 + Simulator::run ();
9.231 + unsigned long long delta = time.end ();
9.232 + double delay = ((double)delta)/1000;
9.233 + std::cout << "runtime="<<delay<<"s"<<std::endl;
9.234 +}
9.235 +
9.236 +
9.237 +int main (int argc, char *argv[])
9.238 +{
9.239 + char const *input = 0;
9.240 + uint32_t n = 1;
9.241 + while (argc > 0) {
9.242 + if (strcmp ("--list", argv[0]) == 0) {
9.243 + Simulator::set_linked_list ();
9.244 + } else if (strcmp ("--heap", argv[0]) == 0) {
9.245 + Simulator::set_binary_heap ();
9.246 + } else if (strcmp ("--map", argv[0]) == 0) {
9.247 + Simulator::set_std_map ();
9.248 + } else if (strncmp ("--n=", argv[0], strlen("--n=")) == 0) {
9.249 + n = atoi (argv[0]+strlen ("--n="));
9.250 + } else if (strncmp ("--input=", argv[0],strlen ("--input=")) == 0) {
9.251 + input = argv[0] + strlen ("--input=");
9.252 + } else if (strncmp ("--log=", argv[0],strlen ("--log=")) == 0) {
9.253 + char const *filename = argv[0] + strlen ("--log=");
9.254 + Simulator::enable_log_to (filename);
9.255 + }
9.256 + argc--;
9.257 + argv++;
9.258 + }
9.259 + if (input == 0) {
9.260 + std::cerr << "need --input=[filename] option" << std::endl;
9.261 + return 1;
9.262 + }
9.263 + LogReader log;
9.264 + log.read_from_filename (input);
9.265 + for (uint32_t i = 0; i < n; i++) {
9.266 + log.run ();
9.267 + }
9.268 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/utils/run-tests.cc Tue Aug 29 17:47:17 2006 +0200
10.3 @@ -0,0 +1,32 @@
10.4 +/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
10.5 +/*
10.6 + * Copyright (c) 2005 INRIA
10.7 + * All rights reserved.
10.8 + *
10.9 + * This program is free software; you can redistribute it and/or modify
10.10 + * it under the terms of the GNU General Public License version 2 as
10.11 + * published by the Free Software Foundation;
10.12 + *
10.13 + * This program is distributed in the hope that it will be useful,
10.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.16 + * GNU General Public License for more details.
10.17 + *
10.18 + * You should have received a copy of the GNU General Public License
10.19 + * along with this program; if not, write to the Free Software
10.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10.21 + *
10.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
10.23 + */
10.24 +
10.25 +#include "yans/test.h"
10.26 +
10.27 +int main (int argc, char *argv[])
10.28 +{
10.29 +#ifdef RUN_SELF_TESTS
10.30 + yans::TestManager::enable_verbose ();
10.31 + yans::TestManager::run_tests ();
10.32 +#endif /* RUN_SELF_TESTS */
10.33 +
10.34 + return 0;
10.35 +}