fi
AM_CONDITIONAL(USE_SIMIX,test x$enable_simix != xno)
+#########################################
+## Build optional modules (gtnets)
+##
+SG_CONFIGURE_PART(Optional modules)
+AC_ARG_ENABLE(gtnets,
+ AS_HELP_STRING([--enable-gtnets], [Use the new GTNetS module (default=no)]),
+ enable_gtnets=$enableval,enable_gtnets=no)
+if test "x$enable_gtnets" = "xyes" ; then
+ AC_MSG_RESULT("***** You have decided to use the experimental GTNetS. We hope you know what you're doing.. ****")
+ AC_DEFINE(USE_GTNETS, 1, [Indicates whether we should use GTNetS or not])
+else
+ AC_MSG_RESULT(Eventually you will come to GTNetS: x$enable_gtnets)
+fi
+AM_CONDITIONAL(USE_GTNETS,test x$enable_gtnets != xno)
+
#########################################
## Check for libraries extra-dependencies
##
--- /dev/null
+
+#include "gtnets_simulator.h"
+#include "gtnets_interface.h"
+
+static GTSim* gtnets_sim = 0;
+
+// initialize the GTNetS interface and environment
+int gtnets_initialize(){
+ if (gtnets_sim){
+ fprintf(stderr, "gtnets already initialized.\n");
+ return -1;
+ }
+ gtnets_sim = new GTSim();
+ return 1;
+}
+
+// adds a link (argument link is just an index starting at 0...
+// add link 0, add link 1, etc.)
+int gtnets_add_link(int id, double bandwidth, double latency){
+ return gtnets_sim->add_link(id, bandwidth, latency);
+}
+
+// adds a route between a source and a destination as an array of link indices
+// (note that there is no gtnets_add_network_card(), as we discover them
+// on the fly via calls to gtnets_add_route()
+int gtnets_add_route(int src, int dst, int* links, int nlink){
+ return gtnets_sim->add_route(src, dst, links, nlink);
+}
+
+// create a new flow on a route
+// one can attach arbitrary metadata to a flow
+int gtnets_create_flow(int src, int dst, long datasize, void* metadata){
+ return gtnets_sim->create_flow(src, dst, datasize, metadata);
+}
+
+// get the time (double) until a flow completes (the first such flow)
+// if no flows exist, return -1.0
+double gtnets_get_time_to_next_flow_completion(){
+ return gtnets_sim->get_time_to_next_flow_completion();
+}
+
+// run until a flow completes (returns that flow's metadata)
+int gtnets_run_until_next_flow_completion(void ***metadata, int *number_of_flows){
+ return gtnets_sim->run_until_next_flow_completion(metadata, number_of_flows);
+}
+
+// run for a given time (double)
+int gtnets_run(Time_t deltat){
+ gtnets_sim->run(deltat);
+}
+
+// clean up
+void gtnets_finalize(){
+ if (!gtnets_sim) return;
+ gtnets_sim->finalize();
+ delete gtnets_sim;
+ gtnets_sim = 0;
+}
+
--- /dev/null
+// Interface for GTNetS.
+// Kayo Fujiwara 1/8/2007
+
+#ifndef _GTNETS_INTERFACE_H
+#define _GTNETS_INTERFACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ int gtnets_initialize();
+ int gtnets_add_link(int id, double bandwidth, double latency);
+ int gtnets_add_route(int src, int dst, int* links, int nlink);
+ int gtnets_create_flow(int src, int dst, long datasize, void* metadata);
+ double gtnets_get_time_to_next_flow_completion();
+ int gtnets_run_until_next_flow_completion(void*** metadata, int* number_of_flows);
+ int gtnets_run(double delta);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
--- /dev/null
+//Kayo Fujiwara 1/8/2007
+#include "gtnets_simulator.h"
+#include "gtnets_topology.h"
+#include <map>
+
+void static tcp_sent_callback(int id, double completion_time);
+
+// Constructor.
+// TODO: check the default values.
+GTSim::GTSim(){
+ int wsize = 20000;
+ is_topology_ = 0;
+ nflow_ = 0;
+ sim_ = new Simulator();
+ topo_ = new SGTopology();
+
+ // Set default values.
+ TCP::DefaultAdvWin(wsize);
+ TCP::DefaultSegSize(1000);
+ TCP::DefaultTxBuffer(128000);
+ TCP::DefaultRxBuffer(128000);
+
+}
+GTSim::~GTSim(){
+
+ map<int, Linkp2p*>::iterator it;
+ for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
+ delete it->second;
+ }
+ map<int, SGLink*>::iterator it2;
+ for (it2 = tmp_links_.begin(); it2 != tmp_links_.end(); it2++){
+ delete it2->second;
+ }
+ map<int, Node*>::iterator it3;
+ for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
+ delete it3->second;
+ }
+ map<int, TCPServer*>::iterator it4;
+ for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
+ delete it4->second;
+ }
+ map<int, TCPSend*>::iterator it5;
+ for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
+ delete it5->second;
+ }
+ //TODO delete other objects!
+}
+
+
+int GTSim::add_link(int id, double bandwidth, double latency){
+ if (gtnets_links_.find(id) != gtnets_links_.end()){
+ fprintf(stderr, "can't add link %d. already exists.\n", id);
+ return -1;
+ }
+ gtnets_links_[id] = new Linkp2p(bandwidth, latency);
+ return 0;
+}
+
+int GTSim::add_route(int src, int dst, int* links, int nlink){
+ topo_->add_link(src, dst, links, nlink);
+ // topo_->create_tmplink(src, dst, links, nlink);
+ return 0;
+}
+
+void GTSim::create_gtnets_topology(){
+ //TODO: add manual routing
+ //TODO: is this addressing fine?
+ static unsigned int address = IPAddr("192.168.0.1");
+ tmp_links_ = topo_->get_links();
+ map<int, SGLink*>::iterator it;
+
+ //By now, all links has two nodes.
+ //Connect left and right with the link.
+ for (it = tmp_links_.begin(); it != tmp_links_.end(); it++){
+ it->second->print();
+ //both nodes must be not null. TODO check it!
+ int linkid = it->second->id();
+ int leftid = it->second->left_node()->id();
+ int rightid = it->second->right_node()->id();
+
+ cout << "linkid: " << linkid << endl;
+ cout << "leftid: " << leftid << endl;
+ cout << "rightid: " << rightid << endl;
+
+
+ map<int, Node*>::iterator nodeit = gtnets_nodes_.find(leftid);
+ // if the nodes don't exist, add one.
+ if (nodeit == gtnets_nodes_.end()){
+ gtnets_nodes_[leftid] = new Node();
+ gtnets_nodes_[leftid]->SetIPAddr(address++);
+ //add host-node relationships.
+ vector<int> tmphosts = it->second->left_node()->hosts();
+
+ for (int i = 0; i < tmphosts.size(); i++){
+ gtnets_hosts_[tmphosts[i]] = leftid;
+ cout << "host: " << tmphosts[i] << " node: " << leftid << endl;
+ }
+
+ }
+ nodeit = gtnets_nodes_.find(rightid);
+ if (nodeit == gtnets_nodes_.end()){//new entry
+ gtnets_nodes_[rightid] = new Node();
+ gtnets_nodes_[rightid]->SetIPAddr(address++);
+
+ //add host-node relationships.
+ vector<int> tmphosts = it->second->right_node()->hosts();
+
+ for (int i = 0; i < tmphosts.size(); i++){
+ gtnets_hosts_[tmphosts[i]] = rightid;
+ cout << "host: " << tmphosts[i] << " node: " << rightid << endl;
+ }
+ }
+
+ gtnets_nodes_[leftid]->
+ AddDuplexLink(gtnets_nodes_[rightid], *gtnets_links_[linkid]);
+
+ }
+}
+
+int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
+ if (is_topology_ == 0){
+ create_gtnets_topology();
+ is_topology_ = 1;
+ }
+ //TODO: what if more than two flows?
+ //TODO: check if src and dst exists.
+ //TODO: should use "flowID" to name servers and clients.
+ gtnets_servers_[nflow_] = (TCPServer*)gtnets_nodes_[gtnets_hosts_[dst]]->
+ AddApplication(TCPServer(TCPReno()));
+ gtnets_servers_[nflow_]->BindAndListen(80);
+
+ gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[gtnets_hosts_[src]]->
+ AddApplication(TCPSend(nflow_, gtnets_nodes_[gtnets_hosts_[dst]]->GetIPAddr(),
+ 80, Constant(datasize), TCPReno()));
+ gtnets_clients_[nflow_]->SetSendCallBack(tcp_sent_callback);
+ gtnets_clients_[nflow_]->Start(0);
+ nflow_++;
+
+ return 0;
+}
+
+Time_t GTSim::get_time_to_next_flow_completion(){
+ int status;
+ Time_t t1;
+ int pfds[2];
+
+ pipe(pfds);
+
+ t1 = 0;
+ if (fork() != 0){
+ read(pfds[0], &t1, sizeof(Time_t));
+ waitpid(-1, &status, 0);
+ }else{
+ Time_t t;
+ t = sim_->RunUntilNextCompletion();
+ write(pfds[1], (const void*)&t, sizeof(Time_t));
+ exit(0);
+ }
+ return t1;
+}
+
+int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
+ Time_t t1 = sim_->RunUntilNextCompletion();
+ sim_->Run(t1);
+ //TODO set metadata and number of flows.
+ return 0;
+}
+
+int GTSim::run(double delta){
+ sim_->Run(delta);
+ return 0;
+}
+
+// Clean up.
+int GTSim::finalize(){
+ //TODO
+ is_topology_ = 0;
+ delete sim_;
+ delete topo_;
+ return 0;
+}
+
+void static tcp_sent_callback(int id, double completion_time){
+ // Schedule the flow complete event.
+ SimulatorEvent* e =
+ new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
+ Simulator::instance->Schedule(e, 0, Simulator::instance);
+
+ //TODO: set metadata
+ printf("In tcp_sent_callback: flow id: %d, time: %f\n", id, completion_time);
+}
+
--- /dev/null
+//Kayo Fujiwara 1/8/2007
+
+#ifndef _GTNETS_SIM_H
+#define _GTNETS_SIM_H
+
+#ifdef __cplusplus
+#include "gtnets_topology.h"
+
+#include <iostream>
+#include <sys/wait.h>
+#include <map>
+
+//GTNetS include files
+#include "simulator.h" // Definitions for the Simulator Object
+#include "node.h" // Definitions for the Node Object
+#include "linkp2p.h" // Definitions for point-to-point link objects
+#include "ratetimeparse.h" // Definitions for Rate and Time objects
+#include "application-tcpserver.h" // Definitions for TCPServer application
+#include "application-tcpsend.h" // Definitions for TCP Sending application
+#include "tcp-tahoe.h" // Definitions for TCP Tahoe
+#include "tcp-reno.h"
+#include "tcp-newreno.h"
+#include "validation.h"
+#include "event.h"
+
+using namespace std;
+
+//Simulator s;
+class GTSim {
+
+public:
+ GTSim();
+ ~GTSim();
+public:
+ int add_link(int id, double bandwidth, double latency);
+ int add_route(int src, int dst, int* links, int nlink);
+ int create_flow(int src, int dst, long datasize, void* metadata);
+ double get_time_to_next_flow_completion();
+ int run_until_next_flow_completion(void*** metadata, int* number_of_flows);
+ int run(double deltat);
+ int finalize();
+
+ void create_gtnets_topology();
+private:
+ Simulator* sim_;
+ SGTopology* topo_;
+ int nnode_;
+ int is_topology_;
+ int nflow_;
+
+ map<int, Linkp2p*> gtnets_links_;
+ map<int, Node*> gtnets_nodes_;
+ map<int, TCPServer*> gtnets_servers_;
+ map<int, TCPSend*> gtnets_clients_;
+ map<int, SGLink*> tmp_links_;
+ map<int, int> gtnets_hosts_; //<hostid, nodeid>
+ map<int, void*> gtnets_metadata_;
+};
+
+#endif /* __cplusplus */
+
+#endif
+
+
--- /dev/null
+
+//SGNode, SGTopology: tmporary classes for GTNetS topology.
+
+#include "gtnets_topology.h"
+
+//
+// SGNode
+//
+// TODO when merging a node, remember to add the existing "hosts".
+SGNode::SGNode(int id, int hostid){
+ ID_ = id;
+ if (hostid >= 0)
+ hosts_.push_back(hostid);
+}
+
+SGNode::~SGNode(){
+ //TODO
+}
+
+void SGNode::add_link(SGLink* newlink){
+ links_.push_back(newlink);
+}
+
+
+SGLink* SGNode::other_link(int linkid){
+ for (int i = 0; i < links_.size(); i++){
+ if (links_[i]->id() != linkid)
+ return links_[i];
+ }
+ return NULL;
+}
+
+bool SGNode::has_link(SGLink* link){
+ for (int i = 0; i < links_.size(); i++){
+ //TODO can compare by object itself?
+ if ((links_[i]->id()) == (link->id()))
+ return true;
+ }
+ return false;
+}
+
+void SGNode::print_hosts(){
+ cout << "hosts[";
+ for (int i = 0; i < hosts_.size(); i++){
+ cout << hosts_[i] << ",";
+ }
+ cout << "] ";
+}
+
+void SGNode::print_links(){
+ cout << "links[";
+ for (int i = 0; i < links_.size(); i++){
+ cout << links_[i]->id() << ",";
+ }
+ cout << "]" << endl;
+}
+
+vector<SGLink*>& SGNode::links(){
+ return links_;
+}
+vector<int>& SGNode::hosts(){
+ return hosts_;
+}
+
+//
+// SGLink
+//
+SGLink::SGLink(int id, SGNode* left, SGNode* right)
+ :ID_(id),
+ left_node_(left),
+ right_node_(right){}
+
+
+SGLink::~SGLink(){
+
+}
+
+// add_left_linK: tow things.
+// add the link to the corresponding node.
+// add the corresponding node to the new link.
+// (change from the tmp node to the correct node)
+void SGLink::add_left_link(SGLink* newlink, int side){
+ if (!left_node_){
+ //if alllinks don't have a node, then copy it from
+ //tmporary link.
+ if (side == LEFTSIDE){
+ left_node_ = newlink->left_node_;
+ } else if (side == RIGHTSIDE){
+ left_node_ = newlink->right_node_;
+ } else {
+ cout << "should not come here. side: " << side << endl;
+ }
+ } else {
+ // if already exists, then add the new link to the existing node.
+ left_node_->add_link(newlink);
+ }
+
+ if (side == LEFTSIDE){
+ newlink->left_node_ = left_node_;
+ //printf("link[%d] new left node: %d\n", link.ID, @left_node.ID)
+ }else if (side == RIGHTSIDE){
+ newlink->right_node_ = left_node_;
+ //printf("link[%d] new left node: %d\n", link.ID, @left_node.ID)
+ }else{
+ cout << "should not come here. side: " << side << endl;
+ }
+
+}
+
+void SGLink::add_right_link(SGLink* newlink, int side){
+ if (!right_node_) {
+ //if alllinks doesn't have a node, then copy it from
+ //tmporary link.
+ if (side == LEFTSIDE){
+ right_node_ = newlink->left_node_;
+ }else if (side == RIGHTSIDE){
+ right_node_ = newlink->right_node_;
+ }else{
+ cout << "should not come here. side: " << side << endl;
+ }
+ }else{
+ right_node_->add_link(newlink);
+ }
+
+ if (side == LEFTSIDE){
+ newlink->left_node_ = right_node_;
+ //printf("link[%d] new left node: %d\n", link.ID, @right_node.ID)
+ }else if (side == RIGHTSIDE){
+ newlink->right_node_ = right_node_;
+ //printf("link[%d] new right node: %d\n", link.ID, @right_node.ID)
+ }else{
+ cout << "should not come here. side: " << side << endl;
+ }
+}
+
+bool SGLink::is_inleft(SGLink* link){
+ if (!left_node_)
+ return false;
+ else
+ return left_node_->has_link(link);
+}
+
+bool SGLink::is_inright(SGLink* link){
+ if (!right_node_)
+ return false;
+ else
+ return right_node_->has_link(link);
+}
+
+
+//return the pointer for the left link.
+SGLink* SGLink::left_link(){
+ if (!left_node_){
+ return NULL;
+ }else{
+ return left_node_->other_link(ID_);
+ }
+}
+
+SGLink* SGLink::right_link(){
+ if (!right_node_){
+ return NULL;
+ }else{
+ return right_node_->other_link(ID_);
+ }
+
+}
+
+SGNode* SGLink::left_node(){
+ return left_node_;
+}
+
+
+SGNode* SGLink::right_node(){
+ return right_node_;
+}
+
+
+void SGLink::print(){
+ printf("link[%d]:\n", ID_);
+ if (left_node_){
+ printf(" left node: %d ", left_node_->id());
+ left_node_->print_hosts();
+ left_node_->print_links();
+ }
+
+ if (right_node_){
+ printf(" right node: %d ", right_node_->id());
+ right_node_->print_hosts();
+ right_node_->print_links();
+ }
+}
+
+
+SGTopology::SGTopology(){
+ nodeID_ = 0;
+}
+
+SGTopology::~SGTopology(){
+
+}
+
+
+// TODO: assume that all router-route 1-hop routes are set.
+void SGTopology::add_link(int src, int dst, int* links, int nsize){
+ if (nsize == 1){
+ map<int, SGNode*>::iterator it;
+ it = nodes_.find(src);
+ //if not exists, add one.
+ if (it == nodes_.end()){
+ nodes_[src] = new SGNode(src, src);
+ }
+ it = nodes_.find(dst);
+ //if not exists, add one.
+ if (it == nodes_.end()){
+ nodes_[dst] = new SGNode(dst, dst);
+ }
+
+ map<int, SGLink*>::iterator itl;
+ itl = links_.find(links[0]);
+ //if not exists, add one.
+ if (itl == links_.end()){
+ links_[links[0]] = new SGLink(links[0], nodes_[src], nodes_[dst]);
+ }
+ }
+}
+
+
+//create a temporary link set. (one route)
+// not used now. should clean up...
+void SGTopology::create_tmplink(int src, int dst, int* links, int nsize){
+ map<int, SGLink*> tmplinks;
+
+ SGNode* n1;
+ SGNode* n2;
+
+ int cur = -1;
+ int nex;
+
+ for (int i = 0; i < nsize; i++){
+ if (i == 0) {
+ nodeID_++; //new node
+ n1 = new SGNode(nodeID_, src);
+ }else
+ n1 = n2; //current
+
+ cur = links[i];
+
+ if (i == (nsize-1)){
+ nodeID_++;
+ n2 = new SGNode(nodeID_, dst);
+ }else{
+ nex = links[i+1];
+ nodeID_++; //new node
+ n2 = new SGNode(nodeID_, -1);
+ }
+
+ tmplinks[cur] = new SGLink(cur, n1, n2);
+ if (n1) n1->add_link(tmplinks[cur]);
+ if (n2) n2->add_link(tmplinks[cur]);
+ }
+
+ for (int i = 0; i < nsize; i++){
+ //tmplinks[links[i]]->print();
+ merge_link(tmplinks[links[i]]);
+ }
+ add_tmplink_to_links(tmplinks);
+}
+
+void SGTopology::merge_link(SGLink* link){
+ map<int, SGLink*>::iterator iter;
+ iter = links_.find(link->id());
+ if (iter == links_.end()){
+ //if the link has not been added to the topology.links_, then
+ //printf("link %d doesn't exist in alllinks. No action.\n", link->id());
+ return;
+ }else{
+ int ncommon = 0;
+ int comleft = -1; //if tmplink.left == @alllinks.link.left, 0, otherwise, 1.
+ int comright = -1; //if tmplink.right == @alllinks.link.left, 0, otherwise, 1.
+ //since link is from tmplinks, each link has at most two neibours.
+
+ if (link->left_link()){
+ //printf("common neibor: left_first: %d\n", link->left_link()->id());
+ if (links_[link->id()]->is_inleft(link->left_link())){
+ comleft = 0;
+ ncommon += 1;
+ }
+ if (links_[link->id()]->is_inright(link->left_link())){
+ comleft = 1;
+ ncommon += 1;
+ }
+ }
+
+ if (link->right_link()){
+ //printf("common neibor: right_first: %d\n", link->right_link()->id());
+ if (links_[link->id()]->is_inleft(link->right_link())){
+ comright = 0;
+ ncommon += 1;
+ }
+ if (links_[link->id()]->is_inright(link->right_link())){
+ comright = 1;
+ ncommon += 1;
+ }
+ }
+
+ //printf("common: %d, comright: %d, comleft: %d\n",ncommon, comright, comleft);
+
+ if (ncommon == 0){
+ //merge link.n1 with @alllink.n1, link.n2 with @alllink.n2
+ if (link->left_link())
+ links_[link->id()]->add_left_link(link->left_link(), RIGHTSIDE);
+
+ if (link->right_link())
+ links_[link->id()]->add_right_link(link->right_link(), LEFTSIDE);
+
+ }else if (ncommon == 1){
+ printf("ncommon %d\n", links_[link->id()]->id());
+ //left --> right
+ if ((comleft == -1) && (comright == 0)){
+ if (link->left_link())
+ links_[link->id()]->add_right_link(link->left_link(), RIGHTSIDE);
+ }else if ((comleft == -1) && (comright == 1)){
+ //left --> left
+ if (link->left_link())
+ links_[link->id()]->add_left_link(link->left_link(), RIGHTSIDE);
+ }else if ((comright == -1) && (comleft == 0)){
+ //right --> right
+ if (link->right_link())
+ links_[link->id()]->add_right_link(link->right_link(), LEFTSIDE);
+ }else if ((comright == -1) && (comleft == 1)){
+ //right --> left
+ if (link->right_link())
+ links_[link->id()]->add_left_link(link->right_link(), LEFTSIDE);
+ }else{
+ fprintf(stderr, "should not come here\n");
+ }
+
+ }else if (ncommon == 2){
+ //no change
+
+ }else{
+ fprintf(stderr, "error, common links are more than 2. %d\n", ncommon);
+ }
+ }
+}
+
+void SGTopology::add_tmplink_to_links(map<int, SGLink*> tmplink){
+ map<int, SGLink*>::iterator iter;
+
+ for (iter = tmplink.begin(); iter != tmplink.end(); iter++){
+ map<int, SGLink*>::iterator alliter = links_.find(iter->first);
+ if (alliter == links_.end()){
+ // cout << "tmplink " << iter->first << " not found in links_, adding."
+ // << endl;
+ links_[iter->first] = iter->second;
+ }
+ // cout << "tmplink: " << iter->second->id() << endl;
+ }
+
+}
+
+void SGTopology::print_topology(){
+ map<int, SGLink*>::iterator iter;
+ for (iter = links_.begin(); iter != links_.end(); iter++){
+ iter->second->print();
+ }
+}
+
+void SGTopology::create_gtnets_topology(){
+ map<int, SGLink*>::iterator it;
+ for (it = links_.begin(); it != links_.end(); it++){
+
+ }
+}
+
+map<int, SGLink*>& SGTopology::get_links(){
+ return links_;
+}
+
--- /dev/null
+
+
+#ifndef _GTNETS_TOPOLOGY_H
+#define _GTNETS_TOPOLOGY_H
+
+#include <map>
+#include <vector>
+#include <iostream>
+
+#define LEFTSIDE 0
+#define RIGHTSIDE 1
+
+using namespace std;
+
+class SGLink;
+
+class SGNode{
+
+ public:
+ SGNode(int id, int hostid);
+ ~SGNode();
+
+ void add_link(SGLink*);
+
+ //get other link than the link with the given id.
+ //Note it's only for the case the node has two links.
+ SGLink* other_link(int);
+
+ bool has_link(SGLink*); //TODO can do const SGLink*?
+ void print_links();
+ void print_hosts();
+
+ vector<SGLink*>& links();
+ vector<int>& hosts();
+ int id(){return ID_;};
+
+ private:
+ int ID_;
+ bool ishost_;
+ vector<int> hosts_; //simgrid hosts
+ vector<SGLink*> links_;
+};
+
+class SGLink{
+
+ public:
+ SGLink(int id, SGNode* left, SGNode* right);
+ ~SGLink();
+
+ //for a temporary link set, that is, a link has at most two neibours.
+ SGLink* left_link();
+ SGLink* right_link();
+
+
+ SGNode* left_node();
+ SGNode* right_node();
+
+ bool is_inleft(SGLink*);
+ bool is_inright(SGLink*);
+
+ void add_left_link(SGLink*, int side);
+ void add_right_link(SGLink*, int side);
+
+ int id(){return ID_;};
+
+ void print();
+
+ private:
+ int ID_;
+ SGNode* left_node_;
+ SGNode* right_node_;
+
+};
+
+
+class SGTopology{
+ public:
+ SGTopology();
+ ~SGTopology();
+
+ void add_link(int src, int dst, int* links, int nsize);
+
+ void create_tmplink(int src, int dst, int* links, int nsize);
+
+ void merge_link(SGLink*);
+
+ void add_tmplink_to_links(map<int, SGLink*> tmplink); //???
+
+ void print_topology();
+
+ void create_gtnets_topology();
+
+ map<int, SGLink*>& get_links();
+
+ private:
+ int nodeID_;
+ map<int, SGLink*> links_;
+ map<int, SGNode*> nodes_;
+};
+
+#endif