◆ VACUUM の実行
PostgreSQL ドキュメント定常的なデータベース保守作業の俺様要約
- PostgreSQL はレコードが更新/削除されても物理削除は行わない
- これは
VACUUM
で行うので定期的な実行が必要 - 更新頻度の高いテーブルほど頻繁に
VACUUM
のすること - 普通の
VACUUM
とVACUUM FULL
の 2 種類がある - 普通の
VACUUM
は使われていない領域に再利用可能なマークを付ける - 普通の
VACUUM
は不要領域がファイルの最後でない限りファイル縮小は行わない - 普通の
VACUUM
は他のトランザクションにほとんど影響しない VACUUM FULL
は不要領域の占有領域を削除しファイルを縮小するVACUUM FULL
は他のトランザクションに与える影響も甚大- 一般的には1日1回普通の
VACUUM
をしておけばよい - 全レコードを削除する場合は
TRANCATE
を使えばVACUUM
する必要がない - トランザクション ID は 32 ビットで周回する
- トランザクション ID が周回が発生するとデータ損失が起きる
- 7.2 以降は 10 億トランザクション発行する前に
VACUUM
が必要 - 残りトランザクション数が1000万を下回ると警告が出る
- 残りトランザクション数が100万を下回ると発行が出来なくなる
俺様の理解
- Java の Gabage Collection で例えるなら普通の
VACUUM
= Mark & Swept、VACUUM FULL
= Compact 、Windows で例えるならVACUUM FULL
= デフラグ - 定期処理は1日1回普通の
VACUUM
だけで十分 (VACUUM FULL
はディスク容量を見ながらの不定期で良い?)
◆ バックアップとリストア
PostgreSQL ドキュメントバックアップとリストアの俺様要約
pg_dump
は運用中の実行が可能pg_dump
はテーブル構成や全レコードを SQL で出力する- 出力した SQL を
psql
に流し込むと再構築が可能 - ユーザ等、クラスタまとめてバックアップしたい場合は
pg_dumpall
を使用 - ファイルが大きくなる場合はパイプで圧縮すなり分割するなり
- 単純なファイルコピーによるバックアップは postgreSQL の完全停止が必要 (全切断だけではNG)
- ポイントインタイムリカバリ (PITR) という JFS やロールフォーワードのような障害復旧機構がある
- RITR は WAL ファイルにログ (ジャーナル) を記録している
- WAL ファイルを累積的に保管するだけで任意の時点でのスナップショットが再現できる
- WAL ファイルをバックアップ機で再生すればホットスタンバイを実現できる
俺様の理解
- 小規模システムなら
pg_dump
の定期バックアップで十分 pg_dump
の定期バックアップが現実的でない大規模システムは WAL ファイルで
JDK 1.4 から Java Cryptography Extension (JCE) がコアライブラリに追加されている。これにより Java で DES や AES を使った共有鍵 (秘密鍵) 方式の暗号・復号が気軽に扱えるようになった。
// 暗号化するテキストをバイナリ化 |
キー (バイナリ) から SecretKeySpec
を作成し、Cipher
で暗号化を行う。キーは復号化するときにも使うので、乱数とか日付とか不確定なものは NG。また、使用できるキーのビット長はアルゴリズムに依存してるので注意。
上記のサンプルコードから元のバイナリに戻すには以下の通り。Cipher#init()
に指定するモードが異なるだけである。
// 暗号化で使用したキー |
暗号化・復号化ともにバイナリからバイナリへの変換となる。文字列を暗号化する場合は、いったん getBytes()
でバイナリ化してやる必要があるのだが、実行環境の文字エンコーディングの影響を受けないように "UTF-8"
固定にしておくのが無難。
より強固な暗号を使いたい場合は上記サンプルを元にアルゴリズムを変更してキーのビット幅増やせば良い。
モブログとは、携帯から自分のブログに書き込みが出来る機能。正式名称なのか特定ブログシステムでの呼称か知らないが、ここ FC2 でも blog@fc2.*** 宛てにメールを送るだけでブログに公開される。街で変なものを見かけた場合は素早く写真を撮り、熱が冷めないうちにその場で更新できるのでかなり便利だ。
宛先のメールアドレスは固定となっている。管理画面で 「モブログ用のメールアドレス」 なるものを入力し、そのアドレスから届いたメールは全て自分のブログに掲載されるシステムらしい。
ふと、複数のユーザが同じメールアドレスを登録したらどうなるかという疑問が湧いた。これってセキュリティ上問題があるんじゃないだろうか。ざっとこんな結果が予想される。
- そもそも 「このアドレスは別の人に使われています」 とか出て登録できない
- どのブログにも掲載されない → 「掲載できません」 等の応答あり/なし
- 先または後に登録したアドレスに掲載される
- 両方に掲載される
携帯のメールアドレスを知っている悪意的な第三者 (友達とかそんな類) が居た場合は上記のどれも問題があるのではないだろう。
送信者が意図していないブログに掲載されるという意味で 3 と 4 は明らかにセキュリティ違反、というかバグだろう。また 1 と 2 に関しても他人の悪意的な行為で自分の機能が阻害される事になる。どう転んでも問題があるようだ。
この時点でまだ試していないので、オチ無しだったら済まない…
海に落ちた車をクレーンで引き上げている様子。
クレーン車、到着!
がんばればんがれ!
上がった!
ぬおぉぉぉぉぉぉぉぉぉぉ!!!
あちゃ~
親分登場
余裕で引き上げ
よいしょ、よいしょ
うりゃ~
なんて、結構前にネットで見かけた笑いネタ。
…
だが時が経つにつれ、いつの間にやら一コマ加えられて流布するようになった。
アイヤ~!
ほ、本物か? 何かオチ狙い臭いし、コラ臭いし、だいたい最初見た時はなかったし… 奥の赤いセダンは 2 台目が到着してからは黒のワンボックスに変わってたはず。白いボードも 2 台目が来てからはいなくなってる。
ニセモノだとは思うが、何かもやもやするので Photoshop で弄ってみた。ちょっとした拡縮と平行移動で位置あわせするだけでこんなんなった。
うーん、どう見ても 5 枚目の合成です。本当にありがとうございました。
ネットで探してみたら結構検証されてるのね。こちらのサイト
では事細かに事の背景を調査されているようでした。
HTML の <a> タグを使用して、メールを送信する際に件名 (Subject) と本文を自動挿入する事が出来る。テンプレートの目的で使用しているのをしばしば見かけることがある。
<a href="mailto:your-address@domain?subject=件名&body=本文">メール</a>
<a href="mailto:reg@domain?subject=ID845727506992&body=このまま編集しないで送信すれば登録が完了します。">登録メール</a>
登録を完了するには以下のリンクからメールを送信してください。
登録メール (実在しないアドレスなので本当に送信しないように / このサイトが EUC なんで多分化けますが)
互換性についてなのだが、元々は Netscape Navigator の拡張機能であり RFC によって標準化されているものではない。しかし、かなり昔からあった小技なので (たしか 1998 年頃に買った本には既に載ってたような気がする) そこそこの対応は期待しても良いだろう。
メジャーどころの現行バージョンは対応済みなのでシェア比で見れば相当高いだろう (まぁそれでも未対応ブラウザ/メーラー向けの配慮があるに越したことはない)。手元で確認出来たものと、公式サイトにサポート情報が載ってるものをリストアップしてみた。
-
Mozilla Thunderbird
-
Microsoft Outlook (Outlook Express)
-
Lotus Notes
-
Becky!
-
DoCoMo (i-mode)
-
au (ezweb)
-
Tu-Ka (ezweb)
日本語を扱う場合に URL エンコードが必須かかどうかもちょっとずつ違うようだ。
システム開発では、受信時に処理を振り分ける目的でこの機能を検討しているかもしれない。そういう用途ならメールアドレスのほうに ID を埋め込んでしまった方がクライアント側の互換性は心配する必要がないし、意図しない変更 (何せ Subject や本文だし) のリスクは少なくなる。
<a href="reg845727506992@domain">登録完了</a>
メールサーバ側では reg~ から始まるアドレス宛てのメールを特定のプログラムに渡すよう設定するだけで済む。ただしこれには qmail や postfix のような拡張アドレスに対応した MTA が必要になる。sendmail で構築した既存のシステムを変更しないで対応するのは、残念ながら無理なようだ。
Unix では ~/.forward や /etc/aliases を使用して、メールの受信をトリガーにプログラムを起動することが出来る。
Unix の .forward ファイルは受信したメールを別のアドレスに転送するために使われることが多いのだが、パイプを使用してメールの内容をプログラムに渡すこともできる。記述方法は超簡単、| の後に実行権限のあるファイルを指定するだけ。もちろんシェルスクリプトでも C で作ったバイナリでもかまわない。
| myprogram |
.forward は個人管理のファイルなので、自分が受信したメールを加工処理して別アドレスに転送するような場合によく使用される。例えば vacation を使えば不在通知を自動応答する事も出来る。
一方、/etc/aliases はメールボックスのエイリアスを記述するためのファイルだ。こちらのファイルでも同様にパイプを使用して受信メールをプログラムに渡すことが出来る。
support: |/usr/company/replyandstore.sh |
これを利用して、受信と同時に機械的な応答メールを返し、サポート依頼データベースに保管するといったような使い方が出来る。
.forward, aliases どちらのファイルでも、起動されたプログラムは標準入力 (C の stdin, C++ の cin, Java の System.in) からメールの内容を読み出すことが出来る。まぁ、後は焼くなり煮るなり、至って普通のパイプ処理である。
こんなことが自由に出来てた古きよき時代もあった…
JAI をインストールした後に ImageIO.getReaderMIMETypes() で MIME-Type と照らし合わせて処理してみたのだが、どうも image/bmp の形式だけ意図した動きにならないようだ。
ImageIO がサポートしている MIME-Type に image/bmp が含まれていない動きになってしまうのだ。だがその文字列配列をコンソールに出力するとちゃんと image/bmp と表示される。ImageIO.getImageReadersByMIMEType("image/bmp") は有効な要素を一つも返してくれない。だが ImageIO.read() はちゃんと Windows Bitmap も読み込めるというおかしな現象だ。
アレコレ試行錯誤の末、どうも getReaderMIMETypes() が返す文字列に変な空白が入っているのに気付いた。うーん、バグっぽい… ということで BugParade で検索したら、何とこんなことになっていたのだ。
In BMPImageReaderSpi class you have MIME types defined as follows:
private static String mimeTypes[] = {
"image/bmp, image/x-bmp, image/x-windows-bmp"
};
should it be:
private static String mimeTypes[] = {
"image/bmp", "image/x-bmp, "image/x-windows-bmp"
}
。 。
/ / シポーン
( Д )
見ての通り、文字列配列にすべきところを 1 つのリテラルにしてしまっていたのだ (私が気付いた空白は各要素とコンマの間の空白だった)。こりゃ "image/bmp" とじゃ一致しないはずだわ…
BugParade では一応 JAI 1.1β で FIX という事になっている。手元で試したところ 1.0 では発生しない。つまり 1.0_01 固有の問題ということだ。
これは単に MIME-Type に関連する部分のみで、Windows Bitmap 画像の読み込み/書き込みは問題なくできるようだ。ImageIO + JAI で MIME-Type と絡めて扱う場合はちょっと注意が必要。
JDK 1.4 から導入された Image I/O のおかげで Java から各種フォーマットの画像を簡単に読み書き出来るようになった。
// 画像の読み込み |
標準でサポートされているフォーマットは、JDK 1.4 で GIF (読み込みのみ), JPEG, PNG、JDK 1.5 では加えて Windows (OS/2) Bitmap, Wireless Bitmap が追加されているようだ。どのような形式をサポートしているかは以下のコードで確認できる。
String[] format = ImageIO.getReaderFormatNames(); format = ImageIO.getWriterFormatNames(); |
上記を JDK 1.4 で実行すると:
C:>"c:\Program Files\j2sdk1.4.2_09\bin\java" IIOSupported |
また JDK 1.5 の場合は以下のような出力になる。
C:>"c:\Program Files\jdk1.5.0_05\bin\java" IIOSupported |
JDK 1.6 ではこれに加えて、Unisys の LZW 特許が切れた GIF の書き込みをサポートしている。
これだけサポートされていれば大抵の場合は十分なのだが、TIFF など特定フォーマットのサポートが必須なアプリケーションや、画像変換のようにサポートフォーマットの豊富さがユーザビリティに直結する類のアプリケーションもあるだろう。
そこで Java Advanced Imaging (JAI) を使って Image I/O のサポートフォーマットを増やしてみよう。
前からやろうと思ってたオレサマ・サイト Blog 更新日付の自動表示にやっと対応した。 Ajax を使用して JavaScript から RSS を読み込み、最新記事の日付を表示させている。IE6 と Firefox 1.x で動作確認済み。詳しくは HTML ソース参照。
とはいえ実は大事な部分をごまかしている。セキュリティ制限のため JavaScript からは Blog を運営しているサイトと直接通信できない。こればかりは仕方が無いので、自宅のサーバで毎時 0 分に各 Blog の RSS を取得してオレサマ・サイトにアップロードしている。あればあったで何かと便利な自宅サーバである。
構造的には URL の先が動的な XML を生成するサーブレットなどでも良いから、何かとネタに使えそうな小技である。とはいえ strict data typing のない言語でアレコレ DOM をインスペクトするのはサンダルで屋久島を縦走するに等しい。項目を細分化して送信する必要があるなら、ぶっちゃけ対象要素の ID と innerHTML の値を XML にしてサーバから落とす ─ つまり Ajax を単なるバイパス機能として使用するくらいが勢いが良いだろう。
06.06.09 追記
知り合いからの障害報告で 8日→0日、9日→1日、8月→0月、9月→1月、になってしまうバグを修正。parseInt() に渡す数字の頭が 0 から始まっていると ("08" とか) 8 進数表現と解釈されるのをすっかり忘れてました。
どうやら Mozilla 系 (Firefox, Netscape) のブラウザは <xsl:value-of> の disable-output-escaping 属性を無視するらしい。
XML に記述されている & や < などの文字は XSL の出力方法に適切な形式でエスケープされるのだが、この属性を "yes" に設定することでこの動作を解除する事が出来る。つまり XML に埋め込んだ HTML タグがそのまま利くようになるわけだ。
<?xml version="1.0"?> |
上記のような XML に対して:
<xsl:value-of select="/search-engine" disable-output-escaping="yes" /> |
という記述は Google へのリンクを生成する (もし no にすれば <a href=... という文字がそのまま画面に表示される)。
ほとんどの XSL 対応ブラウザがこの挙動を踏襲しているにもかかわらず、Mozilla は no にした場合と同じ動作になる。しかも Mozilla 開発者によれば W3C 仕様のもにゃもにゃに準拠しているのでバグではない、将来的にも対応する予定も無い、解釈の違いだ、との事だ。
何じゃそりゃ。W3C の仕様にこの属性はちゃんと盛り込まれている。出力結果に非 Valid HTML が混ざるのに現行の設計が対応しておらず、2 重になってるパーサの実行コストにも跳ねるのですぐには対応できない、手を入れたくないというのが実際の本音のようだ。
とりあえず、この問題は JavaScript の力を借りて何とか回避することはできた。
Windows の自動更新が働いたので 2 週間ぶりくらいに ThinkPad を再起動した。なぜだかコマンドプロンプトの java の挙動がおかしくなっている。
C:\>java Hoge |
何だか知らないけどカレントディレクトリのクラスファイルを認識しなくなってるようだ。とりあえず CLASSPATH を表示してみる。
C:\>echo %CLASSPATH% |
…
オオー!! これが噂の QuickTime のクラスパス破壊かー!
QuickTime のインストーラは勝手に環境変数 CLASSPATH を自分のライブラリに書き換えてしまう。そのため、デフォルト状態でカレントディレクトリを参照していたのがある日突然参照されなくなるように見えるのだ。一見 Java とは何の関係も無さそうな QuickTime / iTune などのインストールで発生するので、初心者プログラマやシステムのデプロイヤーがハマるのだ。
ところで最近 QuickTime なんてインストールしたっけか?? QuickTime も iTune もインストールしたのはかなり前だし、とはいえ 「この○○をアプレットから使用できるようにしますか?」 なんてメッセージを最近見た覚えもあるし。うーん、QuickTime の自動更新だろうか… ライセンス購入したのにひどい仕打ちだ orz
最近よく耳にするようになった Ajax (Asynchronous JavaScript and XML)。ブラウザを画面遷移させないで表示内容を入れ替える ─ 要は JavaScript が裏でこっそり通信しますよ、という技法だ (技術ではないな)。Google Maps での地図スクロールだとか、Google Suggest でのキーワード候補表示などを見ると画面の切り替えなしで実現出来ているのが分かる。
入力と結果表示がシームレスに繋がるので使い勝手は格段に向上するわけだが、いかんせんベースの技術が JavaScript である。業務アプリケーションのような特性のシステムであまり凝ったことをするなら、ポータビリティ、対障害性、メンテナンス性などの面でのデメリットの方が大きいだろう (さすがに 「全画面 Ajax で」 ってのは意味が無いのでないだろうが)。
通信結果の XML を参照して条件分岐したり、値を個別のセルに表示したりもできるのだが、JavaScript でそれをやり始めると設計が発散してしまうのは想像に難くない。システム開発で使うなら、画面内の特定領域 (<div> 要素で囲んだ部分) をサーバから取り出した HTML で丸ごと置き換える、といった単純な利用にとどめるのが良いだろう (6 年前にアプレットで似たようなデモ作った記憶が蘇る)。
使い所はどこだろうか? 裏で通信、ということは表の目的が別にあるわけで、つまりオプション機能とかツール、入力補助と言った用途に向いている。画面入力中に裏で新着のお知らせを確認、なんて技だな (クライアントプル技術なのでサーバからのイベント通知は不可)。 Yahoo! 翻訳などがやってるようなポーリング用途は転送量を増やさない意味でも良いかもしれない。
まぁそんな Web 開発向けの Tip 的な小技なのだが、どうも Google 先生が使ってるってんでキーワード付けて焚き付けようって感じが否めない。きっと 「ま た か!」 と思ったエンジニアも多いだろう (だいたい Ajax って名前付けた Jesse James Garrett 氏自体 Google と関係ないし)。
2000 年頃の IT バブル期じゃないんだから、こういう情報キーワード先行な仕掛け方はもうとっくに飽きられてるのにまだ気づいてないのかね。こと最近のは既存の技術・手法・文化にアリガタイ名前付けただけの粗悪品が多いし (少なくとも以前は理論、集大成、改良、あるいは新しい切り口などが付属してた)。「Web2.0」 なんてのはネーミングがいかにも過ぎて笑える。
ここ fc2 ブログもそうなのだが、最近ブラウザで簡易 HTML エディタが機能しているのを目にする機会が増えた。文字の編集だけなら以下のような属性指定だけで簡単に出来るのだ。
<div contenteditable="true"> |
contenteditable 属性は Internet Explorer 5.5 以降でサポートされている。この実行結果は以下の通り。
Internet Explorer だけでなく Firefox もサポートしたい場合は designMode 属性を使えば良い。こちらはページ全体が編集対象になるので、編集領域は iframe として使用する。見た感じ IE 限定なら contenteditable の方が楽そう。
ただ標準で用意されているのは純粋な文字編集機能だけなので、強調・斜体・フォント変更・サイズ変更・リンク・画像貼り付けなど、一通りの編集に対応するなら JavaScript でかなりの作りこみが必要だ。
これで HTML エディタ作ったらとんでもなく大変だろうと思っていたのだが、世の中には根性ある人も居るものだな。世界は広い。
さらに続きである。これで完結である (ことを願う…)。
まずは観測から。
何とかなりそう! ヽ(´ー`)ノ
PostgreSQL で大きなバイナリを扱うには、今まで試した BYTEA 型を使用するほかに OID 型を使用する方法がある。BYTEA 型がバイナリそのものをテーブルに格納するのに対し、OID 型はオブジェクトの ID のみを格納し、実体のバイナリはどこか別のところに保存される (PostgreSQL の場合はシステムカタログのどこかに入るらしい)。
元々 BLOB がロケーション ID やオフセット、長さなどを使って巨大なバイナリを扱うための手段だということを考えれば、むしろこの OID 型を BLOB と呼ぶ方が自然だ (ちなみに商用データベースの方は実体をテーブルスペース外の別ファイルにするか VARBINARY と同様にテーブル内に入れるかなど、きめ細かな構成を選択できるが)。
PostgreSQL の JDBC ドキュメントを参照すると、Java で OID 型を扱うには "LargeObject API" なるものを使わなければならいように見えるが、実は JDBC の java.sql.Blob と互換性のある方法で取り扱えるようになっているようだ。正にこっちが PostgreSQL 的 BLOB なのである。
ネットを検索してみる限り、BYTEA 型を扱うサンプルはいくつか見つかるものの、OID 型を java.sql.Blob で扱う Java チュートリアルはほとんど無いようだ (これが日本語初か?)。なので今回はチュートリアルっぽくまとめてみる。例によってコード簡略化のためリソースのクローズや変数宣言等は省略。
出た! (;´ー`)y─┛~~
前回、InputStream を使って巨大データを BYTEA 型カラムに格納出来たわけだが、今度は保存した内容を取り出すタイミングで再び OutOfMemoryError が姿を現した。
なんだかすごーく嫌な予感がするのだが… とりあえず 8.1 ドライバのソースでも見てみるか。
public InputStream getBinaryStream(int columnIndex) |
. .: : : : : : : : :: :::: :: :: : :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
. . : : : :: : : :: : ::: :: : :::: :: ::: ::: ::::::::::::::::::::::::::::::::::::::
. . .... ..: : :: :: ::: :::::: :::::::::::: : :::::::::::::::::::::::::::::::::::::::::::::
Λ_Λ . . . .: : : ::: : :: ::::::::: :::::::::::::::::::::::::::::
/:彡ミ゛ヽ;)ー、 . . .: : : :::::: :::::::::::::::::::::::::::::::::
/ :::/:: ヽ、ヽ、 ::i . .:: :.: ::: . :::::::::::::::::::::::::::::::::::::::
/ :::/;;: ヽ ヽ ::l . :. :. .:: : :: :: :::::::: : ::::::::::::::::::
 ̄ ̄ ̄(_,ノ  ̄ ̄ ̄ヽ、_ノ ̄ ̄ ̄ ̄
PostgreSQL 7.4.11 (JDBC 3 Driver 7.4.215) の BYTEA (BLOB) 型カラムにファイルの内容を放り込もうと思ったのだが、ファイルサイズが数十MB になると例外が発生してしまうようだ。
java.lang.OutOfMemoryError: Java heap space |
例外が起きなくてもディスクスワップが多発しているようだし、ひょっとしてファイルの全バイナリから巨大な SQL でも組み立てているのだろうか? 今回はそこらへんをちょっと突っ込んで調べてみようと思う。
Mozilla Firefox 1.0.7 (Linux) で XML + XSL を表示させてみたところ
Error loading stylesheet: (null)
http://servername/stylesheet.xsl
などと表示されてしまった。一応 XSLT の処理までは行っているようだが、はてさて原因メッセージが null じゃどこが悪いのか皆目見当も付かず…
試行錯誤の末、どうやら XSL ファイルに対してサーバが返す Content-Type を text/xml にしてやらなきゃダメらしいということまで分かった。text/xsl でもダメなのである。なんとも息苦しい挙動である。
しかもサーバ側で XSLT 処理して HTML 落としてた時と比べて微妙に挙動が違うじゃん! 今までは JavaScript で documet.all("id") とやっていても JavaScript コンソールに警告が出る程度だったのに、何か全面的に禁止になってるみたいだ。うーん、変更の本質でない部分で挙動変わると何か先行き不安だす (´・ω・`)
私が使用している au の携帯電話には GPS 機能が付いている。現在地を確認しながら目的地までリアルタイムにナビゲーションしたり (ez ナビウォーク)、カメラで撮った写真に現在位置を記録できるので便利だ。
旅先で何気ない風景や変な看板なんかを撮るので、以前は 「この写真撮ったのどこだっけ?」 という事がよくあった。初めて車で遠出した時に撮った風車や、瀬戸内の島々が並ぶ風景の場所などは未だに分からない。そんなわけで、位置をメモする代わりに携帯で写真を撮って GPS 情報を付加して保存するようになったわけだ。
最近 GPS に関するネタを調べる機会があったのでちょっと書いてみる。
java.util.Date クラスが immutable じゃないのは、Calendar の登場した 1.1 以降では設計ミスだね。Hashtable と Map インターフェースのように、以前との互換性を保ちつつより抽象化されたインターフェースを乗っけてほしかった。
意図しない変更を避けるために日時データは基本的に long 型で持ちまわるようにしているが、DateFormat で文字列化する時に毎回 Date インスタンスを作成するオーバーヘッドが気にかかる。気にかかると言っても気持ち悪い程度の問題ではあるが。