• ベストアンサー

エラーが出てしまった際に再度処理を実行させる必要のあるケースでのテクニック。

いつもお世話になっております。 PHP5.2.5 Apache1.3.37 SQLite3.3.7 例えば、 fopen()や、sqlite_open()のような関数の場合、 trueが返されないと、その後の処理が進みませんので、 そうならないように、対処したいと考えています。 その方策として、 まず、私が考えたのは、 if(sqlite_open($file_name)){ //該当ファイルが開けたら行われる処理 } elseif(sqlite_open($file_name)){ //再チャレンジ1(きまぐれな「オープンエラー」かもしれないので) } elseif(sqlite_open($file_name)){ //再チャレンジ2(念には念を) } else{ die("致命的なエラーがあるようなので、開けませんでした。"); } ちなみに、sqlite_open()等で、「false」が返ってくる場合というのは、 (1)気まぐれ(ごく稀に、何らかの理由で偶発的に起こる) (2)致命的な問題(常にエラーが吐かれる) この二つが考えられると思っております。 (2)に対する処理は単純で、 エラーが返ってくる際の、 (1)でない場合が、(2)なのだと思います。 問題なのは、(1)の、気まぐれエラーです。 この気まぐれが、どういう理由から起こるのか、 私には全く検討もつきませんが (もっとも、そんなものは、まず起こらないものなのかもしれませんが)、 この気まぐれエラーから、 スクリプト完遂を阻止されないための方策(テクニック)について、 どなたか、アドバイスして下さい。 「気まぐれエラーが訪問者のブラウザに吐かれたら、 リロードしてもらえばいいのでは?」 というのではスマートではない気がするので(実はこれが最もスマートだったり?)、 業界標準的なテクニックがあれば、教えて頂きたいと思っております。 「私は、こんな感じでやってますけども~」 というアドバイスも大歓迎です。^^ どうぞよろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

<?php function sqlite_open_r($file_name){ $retries = 0; $max_retries = 100; do{ if($retries > 0){ usleep(rand(1, 10000)); } $retries += 1; }while((!$obj = @sqlite_open($file_name)) and $retries <= $max_retries); if(is_resource($obj)) return $obj; return false; } ?> http://jp2.php.net/flock flock関数のユーザ投稿の5番目の書き込みを参考にしました。 sqliteがリソースを返すまではusleepでタイミングずらして100回までリトライをかけるというものですね。(業界標準ではないと思います) ただ、mizutakiさんの仰るとおりユーザに再表示を促すほうが良い気はします。 どちらにせよ、DBをmysqlとかに以降した際、使える方法ではないので。

march4
質問者

お礼

今回も多くのことを学ばせて頂きました。 do while文というものを、初めてちゃんと眺めた気がします。 お尻で、繰り返しの条件判断をしているんですね。 usleep()も調べて来ましたが、引数はマイクロ秒扱いなので、 10000という数値でも、たったの、100分の1秒なわけですよね。笑 1~10000のランダム数といっても、人間にとっては、それほど変わらない話ですよね。笑 でも、機械には意味がある、と。 >ただ、mizutakiさんの仰るとおりユーザに再表示を促すほうが良い気はします。 なるほどなるほど。 do while文の仕組みは理解できましたが、 こんな質問を書いておきながら言うのもなんですが、 やや頑張りすぎな処理を導入している感じですよね。 ホゲホゲさんは、それを承知の上で、 あえて、 「もし、そういうことをしたいのであれば、こんなのならありますけど」 と教えて下さったのだと思います。笑 いつも、気を使って頂き、どうもありがとうございます。 で、ちょっと話は変わりますが、 今回、一番印象に残ったことは、 「flock関数のユーザ投稿の5番目の書き込みを参考にしました。」 ここです。笑 英文ドカーンの中から、よくぞ見つけてこられました…。笑 私も見習いたいと思います◎ >どちらにせよ、DBをmysqlとかに以降した際、使える方法ではないので。 保守性、汎用性も考慮頂き、ありがとうございます! この辺りの+αの情報も、毎回参考になっております。

すると、全ての回答が全文表示されます。

その他の回答 (1)

  • mizutaki
  • ベストアンサー率33% (111/333)
回答No.1

気まぐれエラーとはいっても、 そう簡単には起こらないものです。 ファイルをつかんでいても、一瞬で離せば、ほんの少しストップする程度。じゃなければ、いつ開放されるか不明。 そういう類の処理だとsleepを使うことが比較的多いかと思いますよ プログラムの処理時間というものもありますから、 失敗してすぐにアクセスしても、その処理に進むまでにかかる時間は数ミリ秒なんていう、ほぼ間隔無しの時間なので、 その数ミリ秒でエラーが解決されてる可能性は限りなく低い アプリケーションやOSがアクセスする処理でしたらsleepでもいいのですが、 ユーザーが何度もアクセスするような処理の場合でしたら、 率直にエラーにして、 「うまくデータを取得できませんでした。もっかいアクセスしてみてください」 と出したほうが、ユーザーへの負担もCPUへの負担も低くなると思いますよ

march4
質問者

お礼

回答下さり、ありがとうございます。 ・気まぐれエラーは、滅多に起こらない。まず起こらない。---★(1) ・「サーバに大きな負荷が一時的に掛かった」等の理由でエラーが吐かれてしまった場合に、 if,elseifなどの方法では、ifとelseif、それぞれの処理時刻をほとんど隔てられないことから、 結果的に、それぞれから得られる結果はほとんど変わらないことになるため、対策としては有効とは言えない、と。 この視点は私にはないもので、大変有益でした。 私の考えていた「気まぐれエラー」とは、 SF系の話にありがちな危機的状況で例えると、 コンピュータを殴って、 「おい!動け、頼むから動いてくれぇぇ!」 こんな感じです。 つまり、エラー発生が 時刻とは全く関係なく起こり、 その時の叩き具合で変わるような、そんなエラーを、 気まぐれエラーとして想定していました なので、 ご指摘のように、ifとelseifの間には、数ミリ秒くらいの時間的間隔しかありませんが、 叩き具合(叩くタイミング)に意味がある、と私は思っていたので、 ifとelseifによる方法でも、それなりに意味はあると思っていました。 実際、この辺りはどうなのでしょうね。 で、 sleepを使う方法と、 ユーザのリロード依存の方法とを提示頂きましたが、 後者のアクセスタイミングには自由度、つまり、柔軟性がありますよね。 アクセスのトライ回数的にも、時間間隔的にも、 ユーザのさじ加減で、なんとでもなりますから。 一方、前者では、 こちら側で時間と、場合によっては回数を指定することになるわけですから、 その指定しておいたタイミングでは問題が解決されなかった場合には、 結局、ユーザのリロード依存になるわけですよね。 以上のことから(特に、★(1)を重要視)、 ユーザのリロード依存の方法で、問題なさそうだなと感じました。 die("何度アクセスしてもダメな場合は、しばらく時間をあけてトライして下さい"); のようなメッセージを出す設計で検討してみようかと思います。 ※念のため、もう少し、回答を待ってみます。 どうもありがとうございました。

すると、全ての回答が全文表示されます。

関連するQ&A