DAQMWコンポーネント

RedisPubSubパッケージを利用するDAQMWコンポーネントは幾つかあるが、生データをpublishするPublisherMlfをまず紹介する。

PublisherMlf

このコンポーネントはDispatcherMlf等前段のDAQMWコンポーネントからデータを受け取り、Redisサーバにチャネル名(キー名)を持ってそのままデータをpublishする。 publishされたデータは、すでにsubscribeしているSubscirberに送られる。 生データの命名規則は下記の通り。Module Number単位でキー名が必要である。

AAA:edb:AAABBBBBB_CC_DDD_edb
AAAは、装置名で3文字、例えばNVA
BBBBBBはラン番号で6文字の数字、例えば012345
CCはDAQ IDで2文字の数字、例えば00
DDDはModule Numberで3文字の数字、例えば000

このコンポーネントに与えるパラメータは下記の通り。

<params>
  <param pid="daqId">0</param>
  <param pid="infoServerHost">localhost</param>
  <param pid="infoServerPort">6379</param>
  <param pid="isPublishing">yes</param>
  <param pid="srcAddr">192.168.0.16</param>
  <param pid="instId">NVA</param>
  <param pid="eventByteSize">8</param>
</params>

infoServerHostは、Redisサーバのホスト名
infoServerPortは、Redisサーバの使用するポート番号

Redisにエラーが起こらない限り、データはpublishされるが、エラーが起こるとpublishはその後行われなくなる。 上流(DispatcherMlfコンポーネント)から来るデータはその後読み飛ばされる。

#define ENDFLAGという選択肢がある。 これが定義されると、データにエンドマークが実装されているとみなされ、そのデータをチェックする。

エンドマークが実装されている場合、最後のデータが来るとm_end_flagがtrueとなり、 Endコマンドを受けると直ちに以後daq_run()を抜け出し、以後daq_run()には戻らない。 Endコマンドが来ない時は、単に読み出しのタイムアウトを繰り返す。

エンドマークが実装されていない場合あるいはエンドマークをつけたデータが失われた場合は、m_timeoutCountで制御されている。 20を超えない間は、Endコマンドを受けていても、daq_run()を抜け出した後再びdaq_run()に戻り、m_timeoutCountをカウントアップする。 20を超えた時、以後daq_run()を抜け出し以後daq_run()には戻らなくなる。

さて20という値だが、DAQ-Middlewareの入力ポートのデフォルトタイムアウトは5ミリ秒であるので、Endコマンドが到着して以降、20回タイムアウトし100(5x20)ミリ秒を超えてもタイムアウトを起こす場合は、Gathererからのデータはすべて処理されたものとみなす。 この値は確定的な数値ではなく、経験的なものである。 いずれにしても確実に終了を認識するためのアルゴリズムとはならない。

T0EventPublisherMlf

このコンポーネントは、T0EventLoggerMlfがT0インデックスをファイルに書く機能を持つのに対して、RedisサーバにT0インデックスをpublishする機能を持つ。 T0データの命名規則は下記の通り。生データのedbという文字をt0bに替えたものである。 また、PublisherMlfコンポーネント同様に、ENDFLAG の選択が可能である。

AAA:t0b:AAABBBBBB_CC_DDD_t0b

このコンポーネントに与えるパラメータは下記の通り。

<params>
   <param pid="daqId">0</param>
  <param pid="infoServerHost">localhost</param>
  <param pid="infoServerPort">6379</param>
  <param pid="srcAddr">192.168.0.16</param>
  <param pid="isPublishing">yes</param>
  <param pid="instId">NVA</param>
  <param pid="eventByteSize">8</param>
</params>

infoServerHostは、Redisサーバのホスト名
infoServerPortは、Redisサーバの使用するポート番号

DaqInfoPublisher

このコンポーネントは、SubscriberがDaqOperatorからのBegin/Endのタイミングを取得するために作られた。 Subscriberはデータを読むためにBeginの情報やデータ処理を終えるためにEndの情報が必要になる場合がある。 このコンポーネントはBeginやEndの情報をRedisサーバに投げることで、Subscriberがそのタイミングを取得できるようにした。 例えば、下記のようにチャネル名(キー名)を宣言する。

<param pid="keyNameDaqCommand">NVA:DaqInfo:string:DaqCommand</param>

このキー名で送られるメッセージ内容は当面beginやendなどの簡単なものである。

GathererPsdPubコンポーネント

このコンポーネントは、GathererPsdコンポーネントにFIFOオーバーフロー情報をRedisサーバに投げるコードが追加されたものである。 publishされるメッセージのフォーマットはjson。 Redisサーバから取り出して処理するプロセスがPythonなら、jsonモジュールのloadsメソッドでそれらのテキストをオブジェクトに簡単に変換できる。 GathererPsdには、すでにFIFO読み出しのスレッドを走らせてFIFOオーバーフローなどの情報を定期的に読み出せる仕組みがある。

FIFOオーバーフローなどの値を常時モニターするためには1分に1回とかに情報を読み出す必要がある。 Stopwatchメソッドで、そのタイミングを知り送り出すことが出来る。

MakeJson.hは、簡単なjsonストリングを作成するためのクラスである。 それを使って、下記のようなjsonストリングを作ることができ、Redisサーバに送る。

{"time":"2017-01-20T10:11:43JST","daq_id":0,"data":[["192.168.0.16",444444,0],["192.168.0.17",33333,0],["192.168.0.18",22222,0]]}

DAQMWのPublisherMlfとwriteDataToDiskの例

DAQMWのPublisherMlfを走らせて、生データを受けたらLoggerMlfと同じフォーマットでデータを書き込むwriteDataToDiskというSubscriberを走らせる。 このプログラムはRedisPubSubパッケージに含まれている。

利用するGathererはGathererPushで中性子モニタ用検出器(nGEM)のデータを使用する。 DAQMWの構成は下記の通り。

DaqInfoPublisherは独立に走る。
GathererPush -> DispatcherMlf -> PublisherMlf, LoggerMlf

Subscriberを走らせる。この後はDAQMW Web GUIを用いてconfigure->beginを続ける。 そうすると、下記のようにSubscriber::The file is created!と、ファイルを生成し、記録を始める。

./writeDataToDisk 000024 20171206 05 000
The directory,./tmp/NVA000024_20171206/ is created!
Subscriber::init(): status = 0
Subscriber::subsucribe:key-name = NVA:DaqInfo:string:DaqCommand status = 0
Subscriber::subsucribe:key-name = NVA:edb:NVA000024_05_000_edb status = 0
Subscriber::get():time out...
Subscriber::get():time out...
Subscriber::outFile:path-name = ./tmp/NVA000024_20171206/NVA000024_05_000_000.edb
Subscriber::The file is created!
Subscriber::The file is closed!
Subscriber::outFile:path-name = ./tmp/NVA000024_20171206/NVA000024_05_000_001.edb
Subscriber::The file is created!
Subscriber::outFile:path-name = ./tmp/NVA000024_20171206/NVA000024_05_000_002.edb
Subscriber::The file is created!
Subscriber::The file is closed!
Subscriber::get():time out...
Subscriber::get():time out...
Subscriber::finish command has arrived.
Subscriber::The file is closed!

下記のwatchDAQEndAndSendFinish.pyは、DAQの終了をwriteDataToDiskに知らせるpythonプログラムである。

python watchDAQEndAndSendFinish.py
Watch DAQ End and send finish command to subscriber.
Arrived command = begin
Arrived command = end
end command has arrived! Now check the state of DAQMW component.
The state of PubisherMlf0 is now CONFIGURED.
finish command has been sent to Subscriber.
Arrived command = finish

DAQを終了させるために、endコマンドをDAQMW Web GUIを介して発行する。 データ収集は終了する。DaqInfoPublisherはその際、endコマンドをpublishするので、 watchDAQEndAndSendFinish.pyは、それを受けたら、PublisherMlfのstateを読み行き、CONFIGUREDになっていたら、writeDataToDiskにfinishコマンドをpublishする。 このような仕組みを作ることで、writeDataToDiskは確実にPublisherMlfが終了したことを受け自分を終了させることができる。