掲示版のログファイルを違うCGIで共有できるか?

[上に] [前に] [次に]
ぺんぺん 1999/09/22(水) 23:36:18
perlのCGIを用いた掲示板なんですけど、ちがうCGIで同じ一つのログファイルを共有することは出来るのでしょうか?
例えば、A.cgiではminibbs風に表示し、B.cgiではツリー状に表示するといった具合にしたいのですが・・・。
ファイルロックの関係で難しいかなーと思うのですが・・・。

ついでの質問なのですが、cgiプログラムのファイル自体の大きさはサーバーへの負荷にどの程度関係してくるのでしょうか?
よろしくお願いします。

かつべ 1999/09/22(水) 23:50:26
>例えば、A.cgiではminibbs風に表示し、B.cgiではツリー状に表示
>するといった具合にしたいのですが・・・。
(改造すれば)できると思います。というか、できるはずです。
ただ、ツリーの状態を記録した(←日本語へんですかね)デー
タファイルをつくるか、それともデータファイルに記録される
データ構造を工夫するか。ちょっと面倒くさそうですね(^^;

>ファイルロックの関係で難しいかなーと思うのですが・・・。
ファイルロックはあんまり関係ないかと(・・;)

>ついでの質問なのですが、cgiプログラムのファイル自体の大き
>さはサーバーへの負荷にどの程度関係してくるのでしょうか?
それよりも、プログラム自体の処理の方が深刻とは思いつつ、
便乗して私も質問ですが、実際のところどうなのでしょう。
インタプリンタということですが、やはりメモリに全部
持ってきといて処理してるんでしょうか。

ぺんぺん 1999/09/23(木) 00:39:30
>>ファイルロックの関係で難しいかなーと思うのですが・・・。
>ファイルロックはあんまり関係ないかと(・・;)

でも、A.cgiとB.cgiが同時にログファイルにアクセスするとファイルが消えませんかね?
(変なこといってたらごめんなさい)
そこらへんが不安だったもので・・・。

かつべ 1999/09/23(木) 00:54:23
>でも、A.cgiとB.cgiが同時にログファイルにアクセスするとファ
>イルが消えませんかね?(変なこといってたらごめんなさい)
えっと、「読む」だけだったら同時でも大丈夫(なはず)です。
問題は、書き込む時です。
その時はロックファイルをかけてやる必要があります。

でもこれは、今回の時だけでなく、すべてのBBSにいえることです。
同時に書き込みがあることは、最低限想定しなくちゃいけません。

だから、

  ファイルにロックがかかっている(ロックファイルが存
  在する)間は、「ちょっと待ってね」という状態にして、
  それが解けた時に書き込む。

という処理を書けばいいわけです。
これさえやっていれば、二つでも三つでもOKですよ!
(重くなっちゃいそうですが(^^;)

J.Naka 1999/09/23(木) 13:02:21
■複数のCGIがログファイル共有事の問題
 これは、かつべさんの言うように、プログラム的&ロジック的には、全く問題にならないと思います。

■CGIソースサイズとサーバー負荷の因果関係
 これは、ファイルI/Oが無茶苦茶に多いとか無い限り殆ど無視できる範囲ではないでしょうか。(自分はサーバー未経験&UNIX知らない人なので、想像です(^^;)

■排他処理
ロックファイル、つまり排他制御ですよね。
これは、とほほHPにも記述してありますが、ロックは、
書き込み処理の時、

 他からの書き込みロックは当然に、
 他からの読み込みもロックするのが完全のようです。

理由は、書き込み中、つまりデータファイルが不完全状態で他が読み込むと無茶苦茶を読み込む事になるからです。
つまり、書き込みロックはサーバー側の保護が目的で、読み込みロックはクライアント保護が目的ということすね。掲示板は両者が存在して初めて機能するものなので、当然両者ともに保護しないといけないすね。

■掲示板ツーリー表示ロジック
これは、自分も興味あるので、ちとレス。(自分は、まだ手を付けたことないですので、あくまで想像の範囲です(^^;)

これも、かつべさんの言うように、結構難しいような気がします。
ロジック自体(アルゴリズム)の考察も色々な選択肢がありそうで結構悩みそう(^^;
ロジックは決定しても、そのコーディングはやっぱり難儀しそうです。簡単な処理でないだろうから、バグ格闘が永遠と続きそう。←あっ僕の場合すね(^^;

自分の思うのは、
 ツリーの状態、つまり各アーティクルのリンク状態を記録するリンクログファイルとアーティクル本文のログファイルを別に持つ。
理由は、リンク状態というのは1つの要素(リンク先)が数バイトの多次元配列で表現できると思うので、リンクログファイルサイズはアーティクルログファイルサイズよりは相当に小さいと思われる。
よって、煩雑に発生すると思われるリンクの追加・削除つまりリンク修正は出来るだけ小さなファイルI/Oで行うために、リンクとアーティクルは別ファイルとする。
 もう一つは、各ログファイルの構造は、キチキチの設計せずに少し冗長性を持たせプログラム進展に伴うロジック修正&改造に柔軟に対応かのうなようにする。

 ほいでもって(何処の方言じゃ(^^;)、上のデータ構造体から希望の表示形態のHTMLファイルを生成するコードを書くと。さら、ほいでもって、コーディング時に当然データ構造体の問題点がでるだろうから、そこでもう一度最初に戻ってデータ構造を考察すると。。。。と永遠にグルグル回るスパイラル開発状態になると言う訳です(^^;。

 ちなみに、データ構造とかそれへのアクセスコードを分離しないオブジェクト指向的手法がこのようなプログラミングにはかなり有効だと思います。が、Perlのオブジェクト指向はかなり弱いです。

J.Naka 1999/09/23(木) 13:09:42
あ、ロックファイル(排他制御)は、CGI同士の排他でユーザーは関係ないシチュエーションでしたね。(^^; でも、理屈としては同じことかと。

ふじ 1999/09/23(木) 15:34:13
ロックは取りあえず置いておいて、ツリー構造について。

ツリー構造は、各発言のデータにその子発言のID
(不定長になりますが)を持たせるだけで実現できます。

#実際には親発言のIDも持っていた方が何かと便利でしょうね。
#もちろん別ファイルにしても良いです。


例えばある発言 x から始まるツリーを表示するときは、
その発言の子IDを取得する関数を用意して (get_children とします)

sub get_tree{
  my $a;
  my @array;
  @array = get_children($a);
  foreach(@array){
    get_tree($_);
  }
}
で、get_tree(x) としてやれば、再帰的に子供全てを得ることが出来ます。
#子要素をソートするときは @array をソートする。

実は、親発言のIDのみをデータとして持っているだけでも実現可能ですが、
計算量のオーダーが N と N^2 の違いになるので、ツリーが
大きくなると子発言をデータとして保持していた方が速いでしょう。

ぺんぺん 1999/09/26(日) 10:59:24
J.Nakaさん、かつべさんありがとうございました。

複数CGIで一つのログファイルを共有してもどうやらあまり問題は無いようですね。
ただ、最後に気になっているのが「他CGIにたいする排他制御」の問題です。
例えばA.cgiがファイルを読み込み、書き込み中に他のユーザーがA.cgiを起動させてもファイルロックが働けば問題は無いというのは分かります。
しかし、A.cgiのログ読み込み、書き込み中にB.cgiが動かされた場合には、B.cgiの排他制御は出来ないのでは無いでしょうか?
つまりA.cgiのB.cgiに対する排他制御は必要なのでしょうか?また、可能なのでしょうか?

ちなみに、僕は書き込み用のCGIだけを、ふたつのCGIとは別に独立させるという形にして、書き込みの時のファイルロックはだけは出来るようにしようかと考えています。

ふじさんへ
僕はminibbsとかツリーというのは例で出したのですが・・・・。
それでも参考になりました。ありがとうございます。

J.Naka 1999/09/26(日) 21:19:15
■排他制御
 A.cgiが起動中(プロセスA0とする)に更に、A.cgiが起動すると(プロセスA1とする)、A0 A1共にA.cgiに記されたグローバルで永続オブジェクトで同一な排他フラグを参照します。これで、A0とA1は同一な物の状態により、完全な排他制御が出来るわけです。フラグが同一な物であるから同時に2つの異なった状態になり得ないので、A0とA1が見るフラグの状態にバッティングは起き得ないわけです。

 と、前振りして、ではB.cgiのプロセスとA.cgiのプロセスの排他制御はどうするか? やっぱり、同一なフラグの参照しかないわけです。
 この同一な排他フラグ参照コードをB.cgi A.cgi両方に持たせるか、そのコードを別モジュール関数とするかはプログラマの判断しだいということで。
-----------------
と、アマチャアのヘタッピプログラマの御意見でありました。(^^;

J.Naka 1999/09/26(日) 21:29:41
追伸:排他制御
>フラグが同一な物であるから同時に2つの異なった状態になり得ないので、A0とA1が見るフラグの状態にバッティングは起き得ないわけです。

 これは、マシン語レベル(つまりバイナリコードレベル)では一瞬(正確にはフラグの読み出し終了から書き込み開始までの間)に巨人の江川ではないが、空白の間が存在します。この空白の間に他のプロセスからアクセスされると、それは異なるフラグ状態がシステムに存在することになる可能性が高い、というより絶対に起きる。これを排除するには、フラグへのアクセス開始からフラグ状態の確定まではCPUレベルの割り込み禁止が必要と思うのです。
 ですから、少し前に書いた、Perlなどのインタプリタでは完全な排他制御は無理でないかい? となったわけ。(^o^)ちゃんちゃん

とほほ 1999/09/26(日) 23:31:35
> 最後に気になっているのが「他CGIにたいする排他制御」の問題です。
ファイルを読み込み中は「読み込みロック」を、ファイルを書き込み中
は「書き込みロック」をかけてください。「読み込みロック」は、「今
私が読み込んでいるから他の人は書き込んじゃ駄目よ」というロックで
す。「書き込みロック」は、「今私が書き込んでいるから他の人は書き
込んだり、読み込んじゃ駄目よ」というロックです。面倒な場合は読み
込みの時も「書き込みロック」する手もあります。

> Perlなどのインタプリタでは完全な排他制御は無理でないかい?
ロックの完全性とインタプリタかどうかは関係ありません。

wwwboard.cgiで利用しているような、シンボリックリンクやディレクト
リを利用したロックの機構も、ロックに関しては完璧です。ただし、ロ
ックファイルを削除せずにプロセスが終了してしまうことがあるので、
アンロックの方が完璧ではありませんが・・・

また、Perlでも、flock()やセマフォを用いることで完全な排他制御
が可能です。こちらは、アンロックも完璧です。

ふじ 1999/09/27(月) 02:39:25
>ぺんぺんさん
>A.cgiのログ読み込み、書き込み中にB.cgiが動かされた場合には、B.cgiの排他制御は出来ないのでは無いでしょうか?
両方のプログラムで「同じ方法で」ロック、アンロックをすれば問題ないです。

A.cgiで flock を使って、 B.cgi で symlink を使ってロックしようと
してたりすると、それはまともに動きません。

>J.Nakaさん
>フラグへのアクセス開始からフラグ状態の確定まではCPUレベルの割り込み禁止が
>必要と思うのです。
それは OS の仕事だと思うんですが。
#というか、マルチタスク(プロセス)の OS で、その部分を OS に
#任せないのは問題でしょう。

Perlでも結局はOSのシステムコールを呼んでるわけだし。

[上に] [前に] [次に]