| CGI 作成の初歩 | 
          
          
          
             
      
 
             
             | 
          
          
            | 19. 不特定が書き込むファイルの排他処理(ロック処理) | 
          
          
             
            掲示板やチャット、カウンタなど利用する人が1人でない場合で 
            書き込みの処理がある場合、必ず排他処理が必要となります。 
             
            どのような理由で必要なのか、もしその処理が無い場合、どのような不具合の可能性が 
            あるのかを考えてみます。 
             
            【排他処理が無い場合の破損の例】 
            まずは下の排他処理が無い場合に記録ファイルが破損する例を見て下さい。 
            例えば掲示板やチャット、カウンタなどでロック処理が無い場合、以下のイメージのようにAさんが 
            書き込み処理を行っている途中で別のBさんが書き込み処理を行う可能性があります。 
            通常サーバの負荷が低ければ、ある程度の書き込み処理はコンマ何秒といった短い時間で完了 
            してしまう為、同時に書き込み処理が起きてログが破損するなど考えられないと思うかもしれません。 
             
              
             
            しかし実際には自分で更新ボタンなどを押してしまい、連続で書き込み処理を行ってしまったり、 
            サーバの負荷が異常に高い時など、簡単な書き込み処理でも数秒かかる事があるなどの以外にも 
            不特定の人で実行されるスクリプトでは、どのような操作がされるか分かりませんのが、最低限同時 
            書き込みによるログファイルの破損を防ぐ方法を説明してきます。 
             
              
            書き込み時のロック処理をしても、実際の書き出し処理を行っている間にそのプロセスが何らかの形 
            で強制終了してしまった場合などは、このロック処理でログファイルの破損は防ぎきれません。 
            どうしても完全である必要があるものは、書き込みログの他にバックアップを保持しておき、それらと 
            比較して破損していないかをチェックするなどの処理が必要だと思いますが通常、掲示板やカウンタ 
            などでこれらの処理まで追加すると負荷が高くなる為、普通は行わないと思います。 
             
             
             
             | 
          
          
            | ロック処理を行ってみる (mkdir ディレクトリ作成の関数を使う) | 
          
          
             
            ロック処理には symlink や flock を使った方法もありますが、ここでは汎用性の高い 
            mkdir関数 を使ったロック処理を行ってみます。 
             
            下のサンプルソースでは、sample というディレクトリをスクリプトが置かれているディレクトリ内に生成します。 
            1回目にアクセスした場合、ディレクトリの生成は正常に行われ、正常終了のメッセージが表示されますが、 
            2回目にアクセス(ブラウザの更新ボタンを押してください)した場合、既にディレクトリが作成されている為、 
            ディレクトリが作成できないとの表示が出力されます。 
             
             
             
              
            このソースではスクリプトの置かれているディレクトリに sample というディレクトリを作成しますが、 
            その削除は行われませんので、不要な場合は後で削除を行って下さい。 
            削除前には必ず自分の必要なディレクトリで無い事を確認してから削除を行って下さい。 
             
            スクリプト内で作成したディレクトリを削除する場合 rmdir関数 を使って削除を行います。 
            一連の流れは、次の項で簡単なスクリプトにより説明しますのでご参照下さい。 
             
             | 
          
          
            | ロックを解除する | 
          
          
             
            ファイルの削除を行ってみます。 
             
            先の処理ではロックするだけでしたが、次の処理では下のイメージのようにロック処理と 
            ロックの解除処理を行ってみます。 
             
              
             
            下のサンプルソースではロックされていない場合、 test.txt に ロックされていなかったので書き込みました 
            という文章がアクセスするたびに書き込まれていきます。 
            実際に使用するに当って良い例ではないかもしれませんが、正常にロックできて書き込みしロック解除できた 
            場合と、どのような操作や引数を送られるか分かりませんので、自分の作ったスクリプト内で決められた値以外 
            のものを与えられた時の処理も追加した方が安全です。 
             
             
             
              
            上記の他に、プロセスが強制終了してしまった場合にロックファイルが残ってしまう事も考え、 
            ファイルの最終更新日時(この場合更新される事は無いので作成日時)を見て、古いロックは 
            削除(数十秒〜数分)するような処理も必要です。 
            そのような場合にロックが残ってしまうと、それ以降記録が出来なくなります。 
             
             
             | 
          
          
            
             
            次項はCGI から画像を表示する方法をご紹介します。 
            カウンタや条件により表示する画像を変える事ができます。 | 
          
          
              | 
          
          
            
             
             | 
          
          
             |