GraphML によるトポロジー指定

有向グラフによるネットワーク定義

システムのネットワークトポロジーを俯瞰的に定義しておき、各コンポーネントが自分ノードを指定することで、間接的に接続情報を指定する。

ネットワークトポロジーを有向グラフで表す。エッジの向きは connect 側から accept 側への方向とする。

GraphML

GraphMLのサブセットを用いてネットワークを定義する方法を提供している。

ここで簡単に GraphML の書き方を説明する。

<?xml version='1.0' encoding='utf-8'?>
<graphml>
  <graph>
    <node id='node1'>
      <port name='port1'><desc>192.168.1.16:10000</desc></port>
    </node>
    <node id='node2'/>
    <edge source='node2' target='node1' targetport='port1'/>
  </graph>
</graphml>

これは node2 から node1 へのリンクした単純なトポロジーを表現している。

GraphML は XML であり、ルートエレメントは graphml である。graphml の内部に graph 要素を置き、ここでグラフを定義する。

グラフ定義はノード定義とエッジ定義から構成される。ノードは nine システムの各コンポーネントを示し、エッジはノード間の接続を表す。

node2 のノード定義は単純である。

    <node id='node2'/>

node1 の定義は少し複雑になっている。

    <node id='node1'>
      <port name='port1'><desc>192.168.1.16:10000</desc></port>
    </node>

子要素として port が定義されている。GraphML ではノードへの接続ポイントを表すのために使い、nine システムではノードの bind/listen を表すのに用いている。

port の子要素の desc で、bind/listen するアドレスを指定している。GraphML では本来は port の説明を記述する要素であるが、アドレスを簡単に書くために少し目的と外れた使い方をしている。

エッジでは、node2 から node1 へのリンクを定義している。

    <edge source='node2' target='node1' targetport='port1'/>

source が connect するノードで、target は connect 先となるノードである。targetport には target ノードで bind/listen している port を指定する。

config1()

sample/simple_system/graphml.cpp では、上記の GraphML を用いた接続指定を行っている。

const char* xml =
   "<?xml version='1.0' encoding='utf-8'?>"
   "<graphml>"
   "<graph>"
   "<node id='node1'>"
   "<port name='port1'><desc>192.168.1.16:10000</desc></port>"
   "</node>"
   "<node id='node2'/>"
   "<edge source='node2' target='node1' targetport='port1'/>"
   "</graph>"
   "</graphml>";

bool config1(nine::system::SystemServer& sv)
{
   nine::system::GraphML* p = nine::system::GraphML::ParseXml(xml);
   nine::system::LinkInfo* pLink = p->parse("node1");
   bool r = sv.initialize(pLink);
   delete pLink;
   return r;
}

config1() の最初の行で GraphML インスタンスを生成している。 引数の xml は少し上で定義されている文字列定数で、中身は前に見た GraphML ドキュメントである。

次に、この GraphML オブジェクトの parse() 関数を呼んで、LinkInfo オブジェクトを生成している。parse() には自分のノード名を渡している。この名前は GraphML ドキュメントのノードID と同一である必要がある。

後は生成した LinkInfo を用いて Server を初期化した後で、LinkInfo を delete する。 これで node1 の接続設定が完了する。

config2()

config2 は config1 のすぐ下に書かれている。

bool config2(nine::system::SystemServer& sv)
{
   nine::system::GraphML* p = nine::system::GraphML::ParseXml(xml);
   nine::system::LinkInfo* pLink = p->parse("node2");
   pLink->format(std::cout);
   bool r = sv.initialize(pLink);
   delete pLink;
   return r;
}

GraphML::parse() へ渡す自ノードの名前以外は、config1() と全く同じになっている。

単一のネットワーク定義をそれぞれのノードで共有でき、接続設定の管理が簡単になっている。