dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_chan_man.cpp
diff --git a/dol/src/dol/visitor/hdsd/scd/scd_chan_man.cpp b/dol/src/dol/visitor/hdsd/scd/scd_chan_man.cpp
new file mode 100644 (file)
index 0000000..d98e8ea
--- /dev/null
@@ -0,0 +1,216 @@
+#include "scd_chan_man.h"
+
+#include "scd_logging.h"
+
+
+scd_chan_man::scd_chan_man(scd_simulator &sim):
+    _sim(sim), _is_ready(false) {}
+
+
+scd_chan_man::~scd_chan_man()
+{
+    std::list<scd_out_connector*>::iterator coit;
+    std::list<scd_chan_wrapper*>::iterator chit;
+
+    for (coit = _connectors.begin(); coit != _connectors.end(); coit++)
+        delete *coit;
+
+    for (chit = _channels.begin(); chit != _channels.end(); chit++)
+        delete *chit;
+}
+
+
+void scd_chan_man::register_channel(const std::string &name, sc_prim_channel& mchan)
+{
+    if ( _get_channel(name) != NULL )
+    {
+        scd_warn("channel \"" + name + "\" already registered, ignoring...");
+    }
+    else
+    {
+        scd_chan_wrapper* wrap = new scd_chan_wrapper(_sim, name, mchan);
+        _channels.push_back(wrap);
+    }
+
+} // register_channel() - master
+
+
+void scd_chan_man::register_channel(const std::string &name,
+        sc_prim_channel& schan, const std::string &host, const uint16_t port)
+{
+    if ( _get_channel(name) != NULL )
+    {
+        scd_warn("channel \"" + name + "\" already registered, ignoring...");
+    }
+    else
+    {
+        // register channel
+        scd_chan_wrapper* wrap = new scd_chan_wrapper(_sim, name, schan);
+        _channels.push_back(wrap);
+
+        // create connector
+        scd_out_connector* conn = new scd_out_connector(_sim, SCD_CM_CHANNEL,
+                name);
+        conn->connect_to(host, port);
+        _connectors.push_back(conn);
+    }
+
+} // register_channel() - slave
+
+
+void scd_chan_man::init_process()
+{
+    if (_is_ready)
+        return;
+
+    std::list<scd_out_connector*>::iterator coit;
+
+    // check all connectors
+    for (coit = _connectors.begin(); coit != _connectors.end();)
+    {
+        scd_out_connector& conn = **coit;
+
+        // retry to connect if necessary
+        conn.process();
+
+        if (!conn.is_connecting() && !conn.has_connection())
+        {
+            // an error occured
+            scd_error("failed to connect channel \""
+                    + conn.get_name() + "\"");
+
+            delete *coit;
+            coit = _connectors.erase(coit);
+
+            _sim.get_cont_man().set_fail();
+            return;
+        }
+        else if (!conn.is_connecting() && conn.has_connection())
+        {
+            // channel is connected
+            scd_chan_wrapper& chan = *_get_channel(conn.get_name());
+
+            if (chan.is_initialized())
+            {
+                scd_error("channel \""
+                        + conn.get_name() + "\" already connected");
+
+                delete *coit;
+                coit = _connectors.erase(coit);
+
+                _sim.get_cont_man().set_fail();
+                return;
+            }
+            else
+            {
+                scd_info("connected channel \"" + conn.get_name() + "\"");
+                chan.connect(conn.get_connection());
+
+                delete *coit;
+                coit = _connectors.erase(coit);
+            }
+        } // end channel connected
+        else
+        {
+            // still trying to connect
+            coit++;
+        }
+        // end this connector
+    } // end check all connectors
+
+    // check if everything is initiated
+    _check_ready();
+
+} // init_process()
+
+
+void scd_chan_man::connect_channel(const scd_command &c, scd_socket* sock)
+{
+    std::string name = c.get_string();
+
+    scd_chan_wrapper* chan = _get_channel(name);
+
+    if (chan == NULL)
+    {
+        scd_warn("unknown channel \"" + name + "\" supplied by peer");
+        delete sock;
+    }
+    else if (chan->is_initialized())
+    {
+        scd_warn("channel \"" + name + "\" supplied by peer already connected");
+    }
+    else
+    {
+        scd_info("connected channel \"" + name + "\"");
+        chan->connect(sock);
+    }
+    
+} // connect()
+
+
+bool scd_chan_man::ready() const { return _is_ready; }
+
+
+void scd_chan_man::process()
+{
+    std::list<scd_chan_wrapper*>::iterator chit;
+
+    for (chit = _channels.begin(); chit != _channels.end(); chit++)
+        (*chit)->process();
+
+} // process()
+
+
+void scd_chan_man::close()
+{
+    std::list<scd_out_connector*>::iterator coit;
+    std::list<scd_chan_wrapper*>::iterator chit;
+
+    for (coit = _connectors.begin(); coit != _connectors.end(); coit++)
+        (*coit)->close();
+
+    for (chit = _channels.begin(); chit != _channels.end(); chit++)
+        (*chit)->close();
+
+} // close()
+
+
+bool scd_chan_man::_check_ready()
+{
+    if (_is_ready)
+        return true;
+
+    if (_connectors.empty())
+    {
+        std::list<scd_chan_wrapper*>::iterator chit;
+
+        // check all channels
+        for (chit = _channels.begin(); chit != _channels.end(); chit++)
+        {
+            if ( !(*chit)->is_initialized() )
+                return false;
+        }
+
+        // all channels initiated
+        _is_ready = true;
+        return true;
+    }
+    else
+        return false;
+
+} // _check_ready()
+
+
+scd_chan_wrapper* scd_chan_man::_get_channel(const std::string& name)
+{
+    std::list<scd_chan_wrapper*>::iterator chit;
+
+    for (chit = _channels.begin(); chit != _channels.end(); chit++)
+    {
+        if ( (*chit)->get_name() == name )
+            return *chit;
+    }
+
+    return NULL;
+
+} // _get_channel()