bbs.cgi再開発プロジェクト 3
■ このスレッドは過去ログ倉庫に格納されています
>>186 書き込み屋さんは非同期で動くんですか? bbs.cgiがレスポンスを返すのはHTMLの生成が終わった後でなければマズい気がするんですが……。 >186 ファイルに書き出すのはやめた方がいいと思う 極端な話SQL鯖のような感じにリアルタイムで返って来るようにする リアルタイムで返って来ないと・・・ 書き込んだ内容が反映されてない -> なんらかの規制になってると判断する可能性有 2chブラウザのかちゅ〜しゃに至っては書き込み後自動的にdat読み込む >>188 まずいっけ? もし生成が溜まっていても、bbs.cgiがチェックしていればよさそうだけど。 >>189 書き出しはDBIにしておけば、MySQLでもDBI::Fileでも任意のドライバに変えるのは簡単。 今まではfileオープンしてそこに追記していたんだから。 tai64で1つごとにファイル書き込みしたとしても次元が違うぐらい速度が上がると思うけど。 案1 「bby -- スレッド情報一元管理システム」と同じDNS使用 dnsに板とキーを投げる dnsは板・キー・レスカウントを保持 通常は127.0.0.1を返し レス数1000になったら127.0.0.2を返す 案2 レス数管理にSQL鯖使用 >190 >書き出しはDBIにしておけば、MySQLでもDBI::Fileでも任意のドライバに変えるのは簡単。 2つのプログラム(2重起動含む)から1つのファイルを使って大丈夫なのか? DNSはキャッシュされるのでそういう用途には向いていないと思います。 >2つのプログラム(2重起動含む)から1つのファイルを使って大丈夫なのか? そういう泥臭いことを引き受けてくれるのがDBIです。 パフォーマンスを考えるとSQLデータベースになりますが、それはまぁ後々の話として。 インターフェースさえDBIにしておけば後でいくらでも入れ替えられます。 http://module.jp/works.html のPerlによるハイパフォーマンスWebアプリケーションの開発を参考に >192 http://member.nifty.ne.jp/hippo2000/perltips/DBD/file.htm >このモジュールは内部で flock() を使っています。 2つのプロセスから同時に使えない気がするけど *dat書き込みプロセスがtxt経由するファイル使用中にbbs.cgiプロセスが書き込めないのはダメだぞ bbs.cgiプロセスとdat書き込みプロセスはtxt経由ではなくTCP経由ってこと? 突貫工事で一番簡単な方法。 #DATを書き込む前に open(FILE, '>> ../$FORM{'bbs'}/dat/$FORM{'key'}.idx'); print FILE '1'; close(FILE); # レス数取得 $res = -s '../$FORM{'bbs'}/dat/$FORM{'key'}.idx'; # DAT書き込み open(FILE, '>> ../$FORM{'bbs'}/dat/$FORM{'key'}.dat'); print FILE ""; #適当に if ($res >= 1000) { #レスが1000超えてるときは1000ストップ print(FILE "1000 over ..."); close(FILE); chmod(0444, '../$FORM{'bbs'}/dat/$FORM{'key'}.dat'); } else { #通常は何もせずクローズ close(FILE); } 突貫だけあってその後いろいろめんどくさいです。 素人が書き逃げするですよ 8) 512KB越え or datが書き込めない or ロックディレクトリが存在するならエラー 17) subject.txt更新 and 1000越え判定 1000越えててカキコ可能なら ・ロックディレクトリ作成 ・1001カキコ ・chmod --- 成功したらロックディレクトリ消去 1)の前に "keyfile.txt"(増加カウントファイル)のサイズをチェックして 1000いってなかったら"1>>keyfile.txt"を実行 1000超えてたら書き込み失敗 *書き込めなくてもカウントする 書き込めなかったら マイナスカウントファイルを作って・・・ >>196 use IO::File; my $file = = new IO::File; 以下perldoc IO::File参照 後ついでに http://member.nifty.ne.jp/hippo2000/perltips/phpperl.htm PerlよりPHPの方が軽くて速いは本当? mod_perl化さえ出来れば、コンパイル後状態で動作するのでCで書くCGIに次ぐ動作速度になる。 つまりメンテナンス性で考えるとmod_perlで動くようにPerlで書けばOk。 http://p22.aaacafe.ne.jp/ ~deagle/AE/Perl-CGI/IO-SafeFile/transaction.html 排他処理、およびプロセスの頓死対策 >201 排他処理やると ABCDEFG・・・と50ms順番に投稿したとする(cgiの処理は75msかかるとする) 書き込み成功 ACEG・・・ (奇数回) 書き込み失敗 BDFH・・・ (偶数回) こんな感じになる >>202 ロックが取れなかったら書き込み失敗とみなすならそうですが、 ロックは取れなかったら取れるまで待つものなので、 全部がちゃんと書き込めるです。 >203 >ロックは取れなかったら取れるまで待つものなので NHK実況板だけで動作確認して次は NTV実況板・・・と1つの板毎に実装していかないとlive8鯖がいきなり死ぬ可能性あるね よし。レス数はctimeにやらせよう。 1970/1/1 9:0:1 が1レス目ってことで。 するとアレアレ。 subject.txtなんて/bbs/datみるだけであっという間にできちゃったりアレアレ。 flockなんて過去の遺物です。 1000のプロセスが全て並行で動いていることを想定して考えないと。 >>205 お、それ結構(・∀・)ゐゐ!! かも。 ちょっと移転作業がめんどくなりそうだけど。 今1000ストップが遅れてるのってあれでしょ? dat書き込んだあとに/bbs/html/*.htmlからレス数とって、 1000ストップ判定するっていう処理だったかな。 うるおぼえ。 まず、DATに書く前に1000ストップ判定すべきですよ。 これだけでかなり違うかと。 処理順で言えば、DATを書き込む処理からエラーを吐いちゃいけないので、 DATを開くときにエラーにすればいいんじゃないすか? んで、実際書けない時のエラーはずーっと上の方でやっちゃっているわけで、 間の処理が長くていっぱいかけるわけですよ。 「開く前に調べる」 これだけではないかと・・・。 それと、bbs.cgiを作り直すなら、設計からやるように(す use IO::File; use Fcntl qw(:flock :mode); use constant LIMIT_SIZE => 512*1024; $file = new IO::File($DATAFILE, '+<') or DispError("ERROR!", "スレッドが見つからない"); flock($file, LOCK_EX); DispError("ERROR!", "このスレッドには書けない") unless -w $DATAFILE and -s $file < LIMIT_SIZE; @logdat = $file->getlines(); $lognum = scalar @logdat; $file->print("$outdat\n"); $logdat[$lognum++] = "$outdat\n"; if ($lognum >= 1000) { $file->print("1001<><>Over 1000 Thread<>このスレッドは〜\n"); $lognum++; chmod(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, $DATAFILE); } $file->close(); flockを使っていいなら楽なんだけど。 >>205 http://nais.to/ ~yto/tools/kuttuki-counter/ くっつきカウンター と同じアイデアだね。 秒数を進めるところで競合が起こるけど。 今のレス数からepoch + secondすればいいから厳密に1000秒を検知しなくていいのなら面白いね。 >>208 >それと、bbs.cgiを作り直すなら、設計からやるように(す じゃあサブルーチンごとにパラメータとか列記していきましょうよ。 1)から分かる範囲でやりましょう。 泥縄的にアプローチ。 chmodが効かない(全部closeされるまで反映されない?)のが問題なわけで、 (1) chmodと同時に適当なファイル(たとえば「スレッドキー.stop」)も作る (2) サイズオーバーや書込み禁止のチェックと同時に (1) のファイルの存在チェックも行う とすれば、とりあえずは解決するかな、と。 スレッドが1000に達するたびにファイルができるのが難点だけど。 >chmodが効かない(全部closeされるまで反映されない?)のが問題なわけで そうなのか 書き込む直前に1000行ったことを知らせるファイルチェック -> ファイルがあったらエラー 現在の投稿が1000なら1000行ったことを知らせるファイルを作る 実際の書き込み chmodをやる でどうだ >>213 ファイル生成のコストがそれなりにかかりますよ。 ディスクI/Oはなるべく避けたいですし。 そです 1,000 超えて 3,000 とか行くのは いつかなと? その前にチャレンジ版を投入するといいかな? 改善を目指したけど、結果は改悪になるかもしれないけどさ。 今日のめちゃいけはヨモギダ祭りですよ。 あの「ヨモギダ」ですよ。 318 :名無しさん :04/02/28 03:08 ID:atMg9E5Y 2/28(土)ヨモギタ少年愚連隊・記憶編 ←ここ 3/ 2(火)16:00〜16:59・チャンネルα「ヨモギダ・ダイジェスト」 「今週土曜から撮影9年超大型企画ついに解禁ヨモギダ少年と感動の再会最新作」 3/ 3(水)16:00〜16:59・チャンネルα「めちゃ2イケてるッ!(再放送)」 「180日超大作!!岡村大学受験涙と感動ヨモギダ少年3年後の姿」 3/ 4(木)16:00〜16:59・チャンネルα「めちゃ2イケてるッ!(再放送)」 「岡村受験(秘)結果速報・ヨモギダ原宿で盗撮された涙の衝撃映像は」 3/ 5(金)16:00〜16:59・チャンネルα「めちゃ2イケてるッ!(再放送)」 「岡村(秘)大学受験本番・美人教師は19歳東大生・恋と勉強の記録公開」 3/ 6(土)15:25〜17:25・めちゃ2イケてるッ!ヨモギダ完結編 3/ 6(土)ヨモギタ少年愚連隊02編 3/13(土)ヨモギタ少年愚連隊03編 3/20(土)ヨモギタ少年愚連隊04編 今日のブレーメンはたぶんなかなかだと思うけど、単にスレが速いだけでは なかなか再現しないんすよね。 ROMも含めたユーザ数が多くないと、再現しないみたい。 ゴールデンタイムで各局の主力番組が目白押しの時の、 一番の人気番組で発生することが多いみたいだから、、、。 とすると、どれが該当するだろう。 live総合スレで聞いてみるかな。 >>217 peko系実況だけ3000にして人柱にして見るのはどうよと振ってみるテスト。 で、来週金曜1855-2148、TBSでオウム特番あり。 あとテロ朝は1、3、5の深夜、五輪サッカーの予選中継が。 open(OUT, $DATAFILE, "a+"); これが Configration Error になるんですが どうすればいいのかなぁ。。。 >214 >ファイル生成のコストがそれなりにかかりますよ。 「1つのファイル作成」と「数百のプロセス待機」のコストを考えるとどうだろ? 実況板とそれ以外の板でbbs.cgiの使い分けが必要になるかも >>223 open(OUT, "+>>$DATAFILE"); とか? 試してみたが、他プロセスでファイルをopenしているときでも、chmodは効く。 パーミッションはopen時に判定で、print時は関係無いみたい。 となると、以下の部分で1000越えのメッセージいくつも書かれるのが納得いかないが、 もしかして別のところでchmodで書き込み可能にしてない? if(-w $dattemp && $lognum > 999){ open(OVER, ">>$dattemp"); print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OVER); chmod(0555, $dattemp); >>117 で $DATAFILE なのに >>140 で $dattemp なのが気になったり。 >>229 サブルーチンなので、変数名が変わってるだけかと。 >>228 あるbbs.cgiが「1000を超えました」を書いて、 そのbbs.cgiがdatをクローズして、chmodするまでのわずかな時間に、 別のbbs.cgiが書いていると。 典型的な競合状態ってやつではないかなと。 つまり、プログラミング的には「腕の見せ所」のはず。 228じゃないけど あるプロセスがchmodを行って、完了する前に別のプロセスが書き込みモードでopenしてしまう。 すると、最初のプロセスのchmodが完了せず、別のプロセスの書き込み完了まで待たされる。 その間に、さらに別のプロセスがオープンして、、 という感じで、全プロセスがファイルをcloseしない限り、chmodが完了しないのかな。 でも、なんかおかしいな。 ファイルに対する実際の処理は、要求された順番に行われて欲しいのに chmod完了待ちの間に、次のopenが成功してしまうというのはどうも・・ カーネル内部でこの辺の優先度がいじられてるのかな。 http://www.dd.iij4u.or.jp/ ~okuyamak/Documents/NetworkFileSystem.Tune.4.html の真ん中ちょい下で「chmodを優先するのもアリ」と書いてあるけど その逆に「chmodをあとまわし」にしているのかもしれない。 >>233 のリンク先にこんなのがありますね。 http://www.dd.iij4u.or.jp/ ~okuyamak/Documents/NetworkFileSystem.Tune.4.html より引用: File System は、実は、順序による結果の一意決定性の保証をしなくても File System と して動作するものを作ることができる。 たとえば、2つの process がほぼ同時に write() と chmod() を リクエストしてきたとしよう。 一応、順序的には『write→chmod』だとする。 この場合、File System は、 「んー。なんかこの write、時間がかかりそうだな。 先に chmod やるか」 と言って、内部で順序を入れ替えてしまっても、 実は バレナイ 。 ばれないということは (公平性には欠けるかも知れないが)、 File System の実装としては「あり」だと言うことになる。 しかし、write() と chmod() の間の時間が十分に離れていれば、 そしてこの間にこれ以外の リクエストがいっさい来なければ、 write() と chmod() はこの順序通りに実行される。 仮に、同一のファイルに対する write() 並びに chmod() で、 しかも chmod() されると write() が実行できなくなるような場合、 外部から観察した場合のリクエスト順序 と 内部でのリクエスト順序 が一致しなくなる。 しかも、常に一定の結果になれば良いのだが、 その保証が無い場合、journal を利用しても結果が再現できなくなる。 上の例だと、 wirte と chmod が十分時間間隔を開けて到着したので write->chmod の順で ファイルシステムに反映した結果を client に返したのだが、 この直後に system down を起こしたとしよう。 journal を実行する際には write と chmod は十分短い間隔で 要求されるので、 chmod->write の順で実行してしまったら、 同じ結果を得ることはできない。 つまり、>>234 の例とは逆に、chmod()が(コストが高いから等の理由で) なかなかスケジュール(実行)されないということも、当然ありうるということになりますね。 chmodの後の >$lognum++; って、subject.txtに書き込むレス数で使われるはずで、実際subject.txtには 1000以上の数値が書き込まれているから、chmodで待つということは無いと 思うんだけど。 えと、>>197 あるいは >>212 (←これは俺と別の人)の方法はどうでしょう。 これなら over 1000 判定されたら、 すでに 8) 以降にある別プロセスは蹴れないけれど 8) 以前のプロセスは蹴ることができるので、まあ 1050 位で止まると思う。 >>212 の人が言うように泥縄的アプローチではあるけれど。 >>238 chmodに成功しているけど反映に時間がかかると仮定すると > ・chmod --- 成功したらロックディレクトリ消去 はマズいような。 >>238-239 >213-214にあるが ファイルを作らないでやる方法を考える方が先らしい >>239 じゃ、>>212 の方法で、ロックファイル(ディレクトリ)はそのまま残して 後で適当に消すってことで。 >>240 それは I/O 負荷的問題?それともポリシーの問題? 気になったんで、さらっとカーネルソースを読んでみた。 ひさしぶりなんで感覚がよみがえらないけど(ctagsの作り方をすっかり忘れていた私)、 chmod()やfchmod()すると結局、 setfmode()っていうカーネル内の関数が呼ばれて、 その中でvn_start_write(vp, &mp, V_WAIT | PCATCH)して、 それが正常終了しないとVOP_SETATTR(chmodの本体部分)に いきつかないようになってるみたい。 vn_start_write()のコメントを読んでみると、 /* * Preparing to start a filesystem write operation. If the operation is * permitted, then we bump the count of operations in progress and * proceed. If a suspend request is in progress, we wait until the * suspension is over, and then proceed. */ int vn_start_write(vp, mpp, flags) なんてことが書いてあって、V_WAITといういやーなフラグ立ててるみたいだから、 すべてのペンディングになっているwrite()がいったん(カーネル的に)一区切りつかない限り、 VOP_SETATTR()が行われないような予感。 つまり、fchmod()にしても(>>139 )だめっていうことになるすね。 というか、カーネル的にこうなっているということは、chmod()するアプローチでは絶対だめってことじゃん。 うーむ。 >>242 それって今までの処理(書込み禁止のチェック)は破綻ってこと? だとしたら (>212に処理順番を入れて書いた) >213を実行? >>241-242 >>91 もそうなんだけど、だからこそストップ(ロック)ファイルを作成してはと書いてみた。 あらかじめ作っておいてストップするときにリネームするという方法もあるが ディレクトリ内のファイル数が増えるのが難点だなあ。 あと、I/Oを減らしたいなら1001以降のレス数を subject.txtに反映するのを止めるという手もある。 chmodが完了して帰ってくるまでに時間がかかるとすると > ・chmod --- 成功したらロックディレクトリ消去 がイイような。 >>243 超多数のwriteが超同時多発的に出たりすると、vn_start_write()でブロックされて、 VOP_SETATTR()に行かなくなるような気がします。 でも、今10分ぐらい読んでみただけなんで、 このへんは、もっと中身をよく知ってる人に確認すべきな気がしますが。 個人的には、書き込みできないことの判定=ファイルモードが555、というのは いまのままでいいから、1000超えのところだけでも、NNNNNNNNNN.dame とかいう ファイル「も」作ることにして、 書き込めない または そのファイルがあったら 書き込み禁止とかにすべきかなとも思ったり。 今日はそろそろ、おやすみの時間。 読んでみたのはFreeBSD 5.2.1-RELEASEのカーネルなんで、 Linuxでは同じところをどうやってるか、誰かおしえていただけるとうれしいかも。 おやすみなさり。 厳密に必ず1001で止めなきゃ行けないシステムならatomicなアプローチが絶対必要だけど 2chでは10や20オーバーする程度は全然平気なんだから 素直に「書き込む前にレス数を数えて、1000を超えてたら書き込まない」がよろしいかと。 つまり>>122 系統のアプローチで、1001OVER書き込みではなく レス内容の書き込みの前にレス数を判定すると。 問題は、追記モードでopenした場合に読み込みがうまく出来るかだけど、どうだったかな? 読み込みが可能なら問題なしだけど、不可能な場合、書き換えモードでopenしなくちゃいけない。 この場合、排他モードに(又はlock)しないと レスを書き込む前に.datの末尾にseekしてから実際に書き込むまでの間に 別プロセスでの書き込みがはさまってしまうかもしれない。 すると末尾にゴミがついたり書き込みが消えると言うことが頻発してしまう。 で、perl全然知らないんだけど>>122 を元に if (open(OUT, "+>>$DATAFILE")) { @logdat = <OUT>; if (scalar @logdat > 999) { print OUT "$outdat\n"; print OUT "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { print OUT "$outdat\n"; close(OUT); } } print $outdatやclose(OUT)が複数箇所で出て非常によろしくないけど とりあえずwindows上では動作した。 で、そのchmodがうまく効いてくれないのが問題じゃなかったっけ? 1000レスを大幅にオーバーしちゃうのは。 だから、chmod完了待ちの間に大量のwriteリクエストが来ちゃうことが問題なの。 writeがあまり来なくなる(一段落する)と、chmodが完了するから大丈夫。 ↑で動作したと書いたけど、 競合状態(複数プロセス)でどうなるかはテストしてない。 FreeBSD上でどうなるかも。 あ、違う。 すみません。私がアホでした。 さらに if (1000over) { そのままclose(); } を入れないと意味無いんだった。 まとめ。 ・chmodによるロックは高負荷時に効かなくなる。 対策案 まともな対処 ・トランザクション処理をするDBDなどで1000ロック処理をする 分かりやすい対処 ・ファイルシステムでロックファイルを使う 提案 ・泥臭い処理を書くとバグるから、出来るだけCPANの.pm(Perl Module)を流用しよう >>249 if (open(OUT, "+>>$DATAFILE")) { ってのがあるんだ。 入れてみよう。 #open(OUT, ">>$DATAFILE"); #print OUT "$outdat\n"; #close(OUT); if (open(OUT, "+>>$DATAFILE")) { print OUT "$outdat\n"; my @logdat = <OUT>; if(scalar @logdat > 999) { print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } } >>256 版を全サーバに入れました live5 を除く live8/9 は root★さんのもじもじが必要 if(scalar @logdat > 1000) { close(OUT); } この文も入れたほうがいいかと、、 $lognum = @logdat を入れなくて大丈夫? if (scalar @logdat > 1000) { DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); } こうか? #open(OUT, ">>$DATAFILE"); #print OUT "$outdat\n"; #close(OUT); if (open(OUT, "+>>$DATAFILE")) { print OUT "$outdat\n"; my @logdat = <OUT>; $lognum = @logdat; if($lognum > 1000) { DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); close(OUT); } if($lognum > 999) { print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } } こうかな? #open(OUT, ">>$DATAFILE"); #print OUT "$outdat\n"; #close(OUT); if (open(OUT, "+>>$DATAFILE")) { print OUT "$outdat\n"; my @logdat = <OUT>; $lognum = @logdat; if($lognum > 1000) { close(OUT); DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); } elsif($lognum > 999) { print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } } $lognum が宣言してない変数なら、 $lognum = @logdat; ↓ my $lognum = @logdat; でたぶんいいかと。 こうだった #open(OUT, ">>$DATAFILE"); #print OUT "$outdat\n"; #close(OUT); if (open(OUT, "+>>$DATAFILE")) { print OUT "$outdat\n"; my @logdat = <OUT>; my $lognum = @logdat; if($lognum > 1000) { DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); close(OUT); } if($lognum > 999) { print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } } たまに「このスレッドは1000を超えました〜」が書き込まれないような気はしますが、 1000を超えて書き込まれることはなくなるはずです。 ……いいんだろうか。 if($lognum > 999) ↓ elsif($lognum > 999) はなおしてもらわんと結局意味がないような、、 >>267 あー、DispErrorはexitしちゃうんで……。 さらに修正 #open(OUT, ">>$DATAFILE"); #print OUT "$outdat\n"; #close(OUT); if (open(OUT, "+>>$DATAFILE")) { print OUT "$outdat\n"; my @logdat = <OUT>; my $lognum = @logdat; if($lognum > 1000) { close(OUT); DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); } if($lognum > 999) { print OVER "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } } またまた修正 #open(OUT, ">>$DATAFILE"); #print OUT "$outdat\n"; #close(OUT); if (open(OUT, "+>>$DATAFILE")) { print OUT "$outdat\n"; my @logdat = <OUT>; my $lognum = @logdat; if($lognum > 1000) { close(OUT); DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); } if($lognum > 999) { print OUT "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } } >>268 あ、DispErrorでexitするから結局elsifにしなくてもいい、ってことね、、 何か気味悪いなw print OUT "$outdat\n"; を1000over判定の後にして$lognumを++する方が。 もし書き込めなかったら狂っちゃうけど chmod問題の原因はそっちっぽいから。 >>270 1000以上でも書き込みするような気がするけど? 狼で1000いったスレに 1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 が書きこまれないです。 1000で止まってますけど あ、@logdatをhtml/*.html作成とかで使ってるのかな。 >>271 そうです。だから実はcloseも要らないです。 ……まあたしかに行儀は悪いですが。 chmod(0555, $DATAFILE); したファイルには書けないんだから 次のbbs.cgiは早めに判定した方がいいなぁ 512 超え判定と同時にやるのがいいのだろうか? どやってやるの? これはbbs.cgiのかなり前半 my $datsizeis =(stat("$DATAFILE"))[7]; unless( $datsizeis <= 512000){ DispError("ERROR!","ERROR:このスレッドは512kを超えているので書けません!"); } >>272 あ、それ思った。 if (open(OUT, "+>>$DATAFILE")) { my @logdat = <OUT>; my $lognum = @logdat; ++$lognum; if($lognum > 1000) { close(OUT); DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); } print OUT "$outdat\n"; if($lognum > 999) { print OUT "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } } あと、各所で1001が消えてるみたいだけど、気にしない方向で。 変更 if (open(OUT, "+>>$DATAFILE")) { my @logdat = <OUT>; my $lognum = @logdat; ++$lognum; if($lognum > 1000) { close(OUT); DispError("ERROR!", "ERROR:このスレッドには書き込めません。"); } print OUT "$outdat\n"; if($lognum > 999) { print OUT "1001<><>Over 1000 Thread<>このスレッドは1000を超えました。 <br> もう書けないので、新しいスレッドを立ててくださいです。。。 <>\n"; close(OUT); chmod(0555, $DATAFILE); } else { close(OUT); } >>277 それって unless( -s $DATAFILE <= 512000){ DispError("ERROR!","ERROR:このスレッドは512kを超えているので書けません!"); } でよいような気がする。。あとで$datsizeisを別に使うならまだしも。 で、ファイルのパーミッションを取得するのは (stat("$DATAFILE"))[2] だそうです。 >>277 if (!-w $DATFILE) { DispError("ERROR!","ERROR:このスレッドには書き込めません。"); } とか? >>281 あっ、そっちのほうがスマートだね、、じゃあ、 unless( -w $DATAFILE){ DispError("ERROR!","ERROR:このスレッドには書き込めません。"); } unless( -s $DATAFILE <= 512000){ DispError("ERROR!","ERROR:このスレッドは512kを超えているので書けません!"); } こうだとよいのかな?(下はどうでもいいけど、、) 入れてこますか unless( -w $DATAFILE){ DispError("ERROR!","ERROR:このスレッドには書き込めません。"); } unless( -s $DATAFILE <= 512000){ DispError("ERROR!","ERROR:このスレッドは512kを超えているので書けません!"); } でも 二回実行するより stat とったほうがいいのかな? http://www.kaimei.org/note/book_out/eff_perl.html ここの56項にstatよりファイルテスト演算子のほうが 効率がいいと書いてあるぽ。2回だとどうかしらんけど、、 unless (-w $DATAFILE) { DispError("ERROR!","ERROR:このスレッドには書き込めません。"); } unless (-s _ <= 512000) { DispError("ERROR!","ERROR:このスレッドは512kを超えているので書けません!"); } でどうでしょ。 書き込み可能かの判定はaccess()でも出来るけど サイズの判定はstat()じゃないと駄目なので、結局stat()は呼ばれる。 と思うのでstat()1回に一票。 ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる