[Glue!] Application Program Interface 仕様 (C Version 0)


この API は C 言語で実現するエージェントから利用する事を前提として設計されている。

なお、現在、 GlueLogic の機能を検証するために、 Perl による実現を前提とした API も並行して開発中である。


API の利用方法

GlueLogicAPI.c をコンパイルして GlueLogic.o を作り、 ユーザの開発したアプリケーションにリンクしやすい所に置く。 GlueLogicQueue.c をコンパイルし GlueLogicQueue という名前で command search path に入れる。

この様な環境の下で、 C で書かれたアプリケーション・プログラムの中では GlueLogicAPI.h を #include して、 API 関数群を呼び出す。


API の構成

API 関数は大別して 3 種類に分けられる。
これらの関数とアプリケーション・プログラムが容易に情報交換ができるように いくつかの API 変数が定義されている。

API 変数は、システムの実行環境を記述するものと、 Glue Logic Server からの通知メッセージを受け取り、 その通知内容に応じて処理関数を dispatch するための関数管理変数に分けられる。


データ表現

データは以下のように表現する。
#Integer
$FloatingPoint
"CharacterString
@Link
%Expression
UNBOUND


名前の表現

名前はピリオドで区切られた任意個の識別子の列である。 識別子は任意個の英数字から構成される文字列である。 ただし、名前の先頭の文字だけは英字でなければならない。

名前の持つ属性は、 その名前の表現の後にアポストロフィーで区切って属性の識別子を付ける事で表現する。


API データ型定義

この版では以下に示すデータ型が定義されている。 これらはどちらも簡易データベースを実現するために用いられるデータ型で、 perl の連想配列と同様な使い勝手を提供するためのものである。

dictElem
簡易データベースの項目を表現する。

この項目は、項目を探す時に用いるユニークなキーと、そのキーの値を示す値とからできている。 この他に、項目の検索を高速化するためのハッシュ値と、リニアリストを構成するためのリンクを持つ。 幾つかの関数は dictElem を指すポインタを返すが、ハッシュ値やリンクを書き換えないような注意が必要である。

typedef struct dict_elem {
    unsigned int	hash;
    struct dict_elem	*next;
    char		*key, *value;
} dictElem;
dictionary
簡易データベースを表現する。

簡易データベースは dictionary 構造体と dictElem を指すポインタの表(配列)からなる。
初期化時に、予想されるデータベースの最大項目数に従って、ポインタ表を確保する。 その表の要素の数や、ある時点でデータベースに含まれる項目の総数などが、 dictionary 構造体の中に管理情報として含まれる。

簡易データベースの初期化の時に指定した最大項目数を超過する数のデータ項目を 格納してしまった場合でも、動作そのものに異常をきたす事は無い。 しかし、格納するデータの持つキーのばらつきにも依るが、 項目数が最大項目数に近付くころからデータの検索の効率が悪化する場合がある。

typedef struct {
    unsigned int	dictSz, tableSz, mask;
    struct dict_elem	**table;
} dictionary;


API 変数

この版では以下に示す変数が定義されている。
char GlueLogicAgent[]
Glue Logic の Server が Client を識別するシンボル名称が入る。 GlueLogicConnect 関数の呼び出し前に文字列が代入されている時にはその値が実際に使われ、 空文字列であった場合は環境変数または GlueLogicConnect 関数の第一引数の値が代入される。
GlueLogicParseArgs 関数を実行した場合には、 標準コマンドライン・オプションである -Agent の値がセットされる。

char GlueLogicServer[]
Server の稼働しているホストとポート番号が入る。 値は文字列で "ServerHost:Port" の形式を採る。 GlueLogicConnect 関数の呼び出し前に文字列が代入されている時にはその値が実際に使われ、 空文字列であった場合は環境変数または GlueLogicConnect 関数の第二引数の値が代入される。
GlueLogicParseArgs 関数を実行した場合には、 標準コマンドライン・オプションである -Server の値がセットされる。

char GlueLogicAnchor[]
他のアプリケーションが Glue Logic 経由で交信する時に使う名前が入る。 GlueLogicConnect 関数の呼び出し前に文字列が代入されている時にはその値が実際に使われ、 空文字列であった場合は環境変数または GlueLogicConnect 関数の第三引数の値が代入される。
GlueLogicParseArgs 関数を実行した場合には、 標準コマンドライン・オプションである -Anchor の値がセットされる。

dictionary GlueLogicParsedArgs
GlueLogicParseArgs 関数を実行した結果、 client の起動コマンドに指定されていたオプションの値が、 オプションの名前をキーとしてセットされる簡易データベース。 値の指定は一般に、 -Option Value の形で与える。 フラグとしてオプション名だけが指定されていた場合は整数 1 が代入される。
この簡易データベースからの値の読み出しは AccessDict 関数によって行なう。

dictionary GlueLogicChangeDispatch
Server から変更通知として Changed xxxx という文字列を受け取った時に、 起動するべき関数を xxxx をキーとしてセットされる簡易データベース。 指定された関数を起動する時には xxxx が引数として渡される。

dictionary GlueLogicMessageDispatch
受け取った変更通知メッセージの最初の単語が Changed でなかった時に、 起動するべき関数を最初の単語をキーとしてセットされる簡易データベース。 指定された関数を起動する時には変更通知メッセージ全体が引数として渡される。


API 関数

この版では以下に示す関数が定義されている。

サーバとの通信を行なう関数

char *GlueLogicConnect( char *AgentID, char *ServerSpec, char *AnchorName )
Glue Logic を初期化し、通信路を確立する関数。 処理に成功すれば AgentID 文字列へのポインタを返し、失敗すれば NULL ポインタを返す。 引数は順に、アプリケーション・エージェント識別子、 Glue Logic Server のホスト名と接続ポート番号、 アプリケーション・エージェントがアンカーとして使う名前、である。
この関数の引数で指定する値は、最も優先度の低い、 default として使うべき値である。 各々に対応する環境変数 ( GLUELOGICAGENT, GLUELOGICSERVER, GLUELOGICANCHOR ) が設定されていればそれらの方が優先して利用され、もしもこの関数が呼び出される前に変数 GlueLogicAgent[], GlueLogicServer[], GlueLogicAnchor[] が設定されている場合には、その値が最も優先して使われる。
この機能は GlueLogicParseArgs がセットした、 標準コマンドライン・オプションから与えられた値を容易に利用できるようにするものである。

void GlueLogicDisconnect()
Glue Logic の通信路を閉鎖する。

処理の成功失敗にか変わらず、どんな値も返さない。

char *GlueLogicAccess( char *buf, int leng, OpList )
Glue Logic とのデータのやりとりを行なう。 処理が成功すればサーバから戻されたデータの先頭を指すポインタを返し、 失敗すれば NULL ポインタを返す。
OpListchar * 型のデータの任意個数のリストで、 各々はサーバへ送るリクエストを含んだ文字列であり、 最後の要素は必ず NULL でなければならない。 操作の指定はクライアント−サーバ間のプロトコルに依存する。

int GlueLogicParseTuple( char **ptr, char **name, char **value )
GlueLogicAccess 関数からの戻り値を使って、 サーバから戻されたデータを C 言語で扱いやすい形で分割する。
サーバから戻って来た文字列をスキャンして、その中に有効なデータがまだ含まれていたならば 1 を返し、 それと同時に *name*value に有効なデータの名前と値を示す文字列へのポインタをそれぞれ代入する。 文字列中にもう有効なデータが含まれていなければ 0 を返す。
*ptr は最初 GlueLogicAccess 関数からの戻り値で初期化し、 GlueLogicParseTuple 関数が文字列をスキャンするのに伴って変化する。
戻って来た文字列の中に何らかのメッセージが含まれていた場合には、 *name には NULL が、*value にはそのメッセージ文字列へのポインタが代入される。

int GlueLogicParseArgs( int argc, char **argv )
アプリケーション起動時のコマンドライン引数の解析を行ない、 何らかのコマンドライン・オプションが指定されていれば、 標準コマンドライン・オプションに関しては GlueLogicAgent[], GlueLogicServer[], GlueLogicAnchor[]の適当な文字列に、 ユーザ定義のオプションに関してはその名前と値とを GlueLogicParsedArgs に入れる。
戻り値として、オプションとは見なせなかった最初の引数の、 argv 配列中の添字を返す。


通知メッセージなどのイベントを処理する関数

void GlueLogicEnqueueMessage()
サーバからの通知メッセージ、 あるいは標準入力からの入力行が到着しているかどうかを調べ、 もしも到着しておればそれぞれを API 内部に用意された待ち行列の最後に追加する。
標準入力からの入力行では、行末の改行文字は取り除かれていない。

void GlueLogicWaitForMessage()
サーバからの通知メッセージの到着、 あるいは標準入力からの入力行の到着の、 いずれかの事象が発生するまで待ち合わせる。

void GlueLogicWaitForChanged( char *Name )
指定した名前 Name に関する通知メッセージが届くまで待ち合わせる。

void GlueLogicDequeueChanged( char *Name )
名前 Name に関する通知メッセージを通知メッセージ待ち行列から削除する。

char *GlueLogicGetMessage( char *buf, int leng )
通知メッセージの待ち行列からメッセージを一つ取り出して buf が指す長さ leng のバッファに入れ、 そのバッファの先頭を指すポインタを返す。 もしも通知メッセージの待ち行列に一つも要素が入っていなければ、 NULL を返す。

char *GlueLogicGetStdin( char *buf, int leng )
標準入力からの入力行の待ち行列からメッセージを一つ取り出して buf が指す長さ leng のバッファに入れ、 そのバッファの先頭を指すポインタを返す。 もしも入力行の待ち行列に一つも要素が入っていなければ、 NULL を返す。
入力行の最後にある改行文字は取り除かれない。

int GlueLogicEndOfMessage()
サーバからの通信路が切断され、かつ、 API 内部の待ち行列が空になった時に 1 を返し、そうでなければ 0 を返す。

int GlueLogicEndOfStdin()
標準入力から EOF が入力され、かつ、 API 内部の待ち行列が空になった時に 1 を返し、そうでなければ 0 を返す。


イベントループを実現する関数

void GlueLogicMainLoop()
簡易データベース GlueLogicChangeDispatch と 簡易データベース GlueLogicMessageDispatch とを用いて、 サーバから変更通知が来た時に対応する処理関数を起動する top level loop を実現する。


簡易データベースを扱う関数

この簡易データベースは、キーと値とがどちらも文字列の形で表現されていることを仮定している。 実際に扱うデータはこの文字列へのポインタである。
データベースの中では、キーを表現する文字列の値は strdup でコピーされるため、 入力時に与えた文字列がその後書き換えられてしまってもデータは正しく保存されるが、 値を表現する文字列へのポインタはコピーせずにそのまま用いられるため、入力時に用いた文字列が破壊されると値を保持できない。 このため、安全のためには strdup 等を行なう必要があるが、そのためのメモリ空間の管理はユーザに任されている。 しかし、データへのポインタをコピーせず、また記憶空間の管理を全てユーザに任せているため、 データベースに出し入れするデータへのポインタを適切に型キャストすることで、 この簡易データベース管理関数群により文字列以外の任意のデータ構造に対するポインタを管理することができる。

dictionary *NewDictionary( dictionary *dict, int size )
新しい簡易データベースを作る。このデータベースは dict で識別される。 この関数は、処理に成功すれば dict に与えた値を返し、エラーが発生すると NULL を返す。
size はデータベースに登録されるデータ項目の最大数の目安で、この値を参考にしてデータ構造を初期化する。 この値はあくまで目安であり、実際に登録されるデータ点数がこの値を越えても障害が発生する心配は無い。 しかし、登録データ点数が目安の値に近付き、更にそれを越えるようになると、アクセスの速度が低下する虞がある。

dictElem *AccessDict( dictionary *dict, char *key )
簡易データベース dict から、 key で示されるキーを持ったデータ項目の dictElem 構造体を探し出す。 データベースに、指定したキーで示されるデータ項目が見つかればそれへのポインタを返し、 そのデータ項目が発見できない時には NULL を返す。

char *RetrieveDict( dictionary *dict, char *key )
簡易データベース dict から、 key で示されるキーを持ったデータ項目の値を捜し出す。 この関数はそのデータ項目があればその値を指すポインタを、無い場合は NULL を返す。
ただし、 NULL が返されたからと言って、そのデータ項目がデータベース中に無いとは断定できない。 データ項目は存在するが、その値が NULL であった場合も考えられる。

char *AssignDict( dictionary *dict, char *key, char *value )
簡易データベース dict の中で、 key で示されるキーを持ったデータ項目の値を value にする。 value の値はそのまま key で示されるキーを持ったデータ項目に書き込まれるため、 このポインタの指す先のデータ構造を破壊しないように注意しなければならない。
この関数は key で示されるキーを持ったデータ項目の、更新前の値を返す。 ただし、それまでデータベース中に存在しなかったキーの場合には、 NULL を返す。 例えば、 valuestrdup した値を与えている場合には、 更新時に返されてくる古い値を free しないとメモリ・リークの原因となる。

char *DeleteDict( dictionary *dict, char *key )
簡易データベース dict の中で、 key で示されるキーを持ったデータ項目そのものを削除する。

この関数は、削除がうまく行けば削除されたデータ項目の削除前の値を返し、 key で示されるキーを持ったデータ項目が発見できなかった場合には NULL を返す。 例えば、 valuestrdup した値を与えている場合には、 削除時に返されてくる古い値を free しないとメモリ・リークの原因となる。

dictElem *EachDict( dictionary *dict, char *ptr )
簡易データベース dict の中の全てのデータ項目について何らかの作業を行なう時に用いる。
全てのデータ項目はデータベースの中で、人間には窺知れない不可思議な法則にしたがって一意に順序づけされており、 この関数を使うと、その順番にしたがって一つづつ全ての項目について処理を行なうことができる。
データベース内の最初の項目を見付ける時には、 ptrNULL を与える。 以降は前回この関数が返して来た値を ptr に与える。 ptr に与えた値がデータベース中の最後の要素であった場合には NULL が戻って来る。
もしも、この関数が返して来たデータ項目を、次の項目を探す前に削除してしまうと、予期しない事態が発生する可能性がある。 また、この関数を使って一連の処理をしている途中に新しい項目が追加されても、 その項目に対しては処理が行なわれない可能性がある。

int IsExist( dictionary *dict, char *key )
簡易データベース dict の中に key で示されるキーを持ったデータ項目があるかどうかを調べ、 もしもあれば 1 を、もしもなければ 0 を返す。


 [M.T. HomePage]  [written & copyrighted by Masayuki Takata]