2013-06-10

srv:SV_ServiceIdentification の利用是非

ちょっと頭パンクする前にメモしておきたい。

地理情報メタデータ標準 ISO 19115 では、メタデータレコードを表わすクラス
MD_Metadata に identification というプロパティ(属性と訳すこともあるがXML属性のことではない、XML要素で表現する)があって、メタデータ自体のプロパティは MD_Metadata 直下に、メタデータが記述
するデータのプロパティは identification の下に記述される。

identification プロパティは抽象クラス MD_Identification を継承する任意のクラスによっていて、INSPIRE とか NOAA/NGDC とかの解説を見ているとそれは
MD_DataIdentification (データ用) と SV_ServiceIdentification である。SV_ServiceIdentification
自体の定義は ISO 19115 から参照される ISO 19119 にある。

UML の世界(ISO 19115)から具体 XML 表現の世界(ISO 19139)に行くと、それは
gmd:MD_Metadata/gmd:identification 内に許される XML 要素が
gmd:MD_DataIdentification または srv:SV_ServiceIdentification であるのだが、名前空間 gmd のスキーマは
http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/gmd/identification.xsd
など ISO サイトにあるのに対し、名前空間 srv のスキーマは
http://schemas.opengis.net/iso/19139/20060504/srv/
http://wis.wmo.int/2011/schemata/iso19139_2007/schema/srv/serviceMetadata.xsd
などサードパーティにしか見当たらない。

これは何としたことか、と思っていたのだが、ISO 19115 の Normative Reference
に ISO 19119 が含まれていないからであり、そして、それは ISO 19115 を実装するのに 19119 は必要ないということであるようだ。

実は、ISO 19115:2003 策定途上の DIS へのコメントで Normative Reference に
19119 を追加しようとして却下されたということがあり、それを読んで疑問が氷解した。


WMO も紆余曲折したが、結局 WCMP 1.3 の文書で SV_ServiceIdentification などへの言及がいっさいないのは、WMO としては、いままでのところ ISO 19115 への適合だけを求めて ISO
19119 への適合を求めていなかったからであるようだ。今となってはわたしが説明しないといけないので、気をつけよう。

2013-06-04

OAI-PMH モニタリングのアルゴリズム(考えてみた)

こんなことしてる場合じゃないんだけど考えを吐きだしておかないと。

OAI-PMH は HTTP ベースで XML の情報を伝送するためのプロトコルです。
http://www.openarchives.org/OAI/openarchivesprotocol.html

元来が図書館・アーカイブの世界でメタデータ(ここでは書誌目録)を共有するためのものであるわけですが、プロトコル自体にはドメイン依存性はそれほどありません。すごく乱暴に言うと RSS 全文フィードに時間範囲
指定機能をつけたようなものです。XML でシリアライズされるレコードにそれぞれ
identifier がついたものが逐次に発生するならば、新しく発生したものを取得することができます。

蛇足ですが、他に、セット(フォルダみたいなもの)とフォーマット変換の機能があって、WMO 情報システム(WIS)のデータカタログではセットが多用される
http://www.wmo.int/pages/prog/www/WIS/wiswiki/tiki-index.php?page=oai-pmh-docu&structure=WIS+up)のですが、それは今回は捨象できます。

さて、差分取得に話を戻します。CGIみたいなクエリパラメタ from と until が指定出来て(どちらもオプショナル)、時間範囲(片方または両方の端が未指定でありうる)の取得ができるわけです。

ふつうは、from に前回実行時刻を指定して、差分だけを取得します。ところが、これを長期間運用すると色々の事情で抜けが生じる。そこをモニターするのが課題です。

一番素朴には、モニターが定期的に過去一切のレコード(識別子だけ取得可能)を取得して、手持ちと見比べるということが考えられます。シンプルなのはいいですが、レコード数に比例して取得時間がかかり、モニター取得間隔が延びていってしまいます。また、エラーレートとと掛け算すると、あるていど多数のレコードを扱う場合には成功率が無限に小さくなってしまいます。

次は、再取得を区分的に行うことが考えられます。このとき、どこからどこまでを再取得したかを保存しておかなければなりません。素朴に考えると

CREATE TABLE harvest(
tfrom DATETIME -- 開始日時 --,
tuntil DATETIME -- 終了日時 --,
tdone DATETIME -- 再取得日時 --,
count DATETIME -- レコード数 --)

みたいなことになりますが、あるレコードの tfrom は前のレコードの tuntil と同じ、という制約を考えると邪魔くさいので、tfrom はヤメにして、

CREATE TABLE harvest(
tuntil DATETIME -- 終了日時 --,
tdone DATETIME -- 再取得日時 --,
count DATETIME -- レコード数 --)

だけあればいいことになります。

再取得は、一定速度でやるのがいいでしょう。定期的にトリガーすると、いつか全数取得の間隔がトリガー間隔を超えたときに二重起動になってしまいます。手前の負荷は耐えられるかもしれませんが、サーバ側で二重アクセスするとエラーレートが増えることが疑われます。

あるいは、WIS では ListSets メソッドでレコード総数を通知する慣例があるので、それがトリガに使えるかもしれません。
http://www.wis-jma.go.jp/meta/oaiprovider.jsp?verb=ListSets
ListSets/set/setDescription/dc/description 要素が "This set contains 161
records" のようなテキストになっている

このへんは、実経験でもんでないので、ちゃんと考えられていません。