Watchdogパターン

Watchdogパターン

リアルタイムシステムで多く使われているWatchdogパターンです。
Watchdogとは、装置を監視したりするプログラムで、他のプログラムから一定の間隔でポーリングや電文の応答を行う機能です。Watchdogプログラム内で、装置のエラーや電文シーケンスのアンマッチなどを見つけると、これらの送り手であるプログラムに通知を行います。
通知は、サービスのリセットやシャットダウンなどが考えられます。組み込み系のプログラミングテクニックとしては、定番になっています。
それでは、具体的にサンプルを見ていきます。この例では、サービスを受けるクラスをChannel、監視を行うのは Watchdogとしました。
図1のクラス図からわかるように、Channelオブジェクトは複数存在できる仕様にしたいので、多重度を使用して表現しています。実際のJavaのコード上では、わかりやすくするためにひとつしか生成していません。

それでは、シーケンス図によるメッセージのやりとりは、図2のようになります。

WatchdogオブジェクトからStart()メッセージをChannelに送り、サービスを開始します。
その後にRequest(1)としてシーケンス番号(1)の電文を送り、番号(2)の電文も続けます。
また、Watchdogオブジェクトでエラーを検出したときには、error()により Restart()メッセージをChannelに送り、サービスをリセットします。実際のJavaのコードは次のようになります。

WatchdogサンプルのJavaコード
                                
    class Channel extends Object{
        PrintPanel pt = new PrintPanel();
        void Start(Watchdog wd){
            pt.Print("Start");
            wd.Request(1); //1番目の電文を送信
            wd.Request(2); //2番目の電文を送信
        }
        void Restart(Watchdog wd){
            pt.Print("Restart");
            this.Start(wd);
        }
    }
    class Watchdog extends Object{
        Channel channel;
        int seq=0; //電文シーケンス番号のチェック用
        PrintPanel pt = new PrintPanel();
        Watchdog(){
            channel=new Channel();
        }
        void Connect(){
            channel.Start(this);
        }
        void Request(int s){
            if (s != seq+1){
                this.error();
            }
            else{
                seq = s;
                pt.Print("Sequesnce No:"+seq);
            }
        }
        void error(){
            pt.Print("Error");
            seq=0;
            channel.Restart(this);
        }
    }

    class PrintPanel{
        void Print(String s){
        System.out.println(s);
        }
    }
                                
                                
Watchdogサンプルのメイン部分
                                
    Watchdog wd;
    wd = new Watchdog();
    wd.Connect();

    エラーが起こったときに、wd.error();
                                
                                

Watchdogオブジェクトがメイン部分で生成されると、ChannelオブジェクトもWatchdogの中で作られます。
サービスの開始を始めたいので、この場合はwd.Connect()を呼び出して、その中でStart()メッセージをChannelに送っています。そうすると図2のシーケンス図の通り、Request(1)、Request(2)として電文をシーケンス番号を付加して送ります。この時の送り先のWatchdogオブジェクトは、 Start(this)として、引数で渡してやります。
ここでは、電文を受け取ったWatchdogオブジェクトは、単純にRequest()の中でシーケンス番号のチェックをしているだけです。さらに、メイン部分でWatchdogオブジェクトにエラーが起きた場合は、wd.error()として、この error()の中でChannelオブジェクトにRestart()を送り、リセットを行います。
このように、装置を監視するようなオブジェクトがある場合に、Watchdogパターンを有効に使うことができます。このWatchdogパターンは、「REAL-TIME UML」Addison -Wesley刊で解説されています。