3.3. ファイルのロック


今回はファイルを同時に書きこみさせないための処理について説明します。
ネットワーク上で動作させるプログラムというのはこういう同時に〜が起こったらというのを考えなければならないので面倒な部分もありますがそれだけたくさんの人に利用してもらえるものだと思ってあきらめましょう。
今回の場合もし掲示板のファイルに同時に書きこみが行われるとファイルが消えてしまうことがあるのでこのような処理が必要になります。

今回の内容はrubyのメーリングリストruby-listで教えていただいたものをそのまま使わせていただきます。
その内容はここで見ることができます。[ruby-list:13141]

-- プログラム 始まり -- test331.cgi

  LOCKDIR = 'lock'



  begin

    Dir.mkdir(LOCKDIR); $LOCKING = true



    # ここで排他的な処理



  rescue Errno::EEXIST # LOCKDIR が存在しているとき

    print "already locked\n"

  ensure

    Dir.unlink(LOCKDIR) if $LOCKING

    $LOCKING = false

  end

-- プログラム 終わり --

このプログラムはこれだけでは動くものではありませんが今回はせっかく教えていただいたのでそのまま転載しました。

ここのやっている内容はファイルの書きこみ(排他的な処理と書いてある部分に入れる予定のものです)を行う前にロック用のディレクトリを作成しておき、ファイルの書きこみが終わったらロック用のディレクトリ消しています。

ちょうど今回は例外処理というものがでているのでそれを重点的に説明します。

1行目ではロック用ディレクトリの名前をLOCKDIRという定数に入れています。
3行目のbeginから13行目のendで例外(エラーなどの事を指す)が起こった場合に対応するための命令です。これが無かったらただ単にエラーが起きます。このbeginはendまでの間で例外が起こったらrescueに飛べという命令になっています。
4行目でLOCKDIRという名のディレクトリを作成し、$LOCKINGというグローバル変数にtrueを入れています。ここでもしすでに存在した場合は8行目のrescueに処理が飛びます。
コメントアウトしてあるところで本当は排他的な処理(ファイルの書きこみ)を行います。
8行目はrescueです。これはもしエラーが起こらずにここまできた場合はbeginを終わるという意味になります。もしくはここで示されるエラー(Errno::EEXIST ファイルが存在していた場合に対応するエラー)が起こっていたら処理がここに来ます。
9行目では「already locked」(すでにロックされているよ)と表示します。
10行目のensureはbeginを終わる前にここの部分を行いなさいという命令です。例外が起ころうと起こらなかろうと必ずここに処理が飛んできます。
11行目で$LOCKINGがtruならLOCKDIRのディレクトリを消しなさいという命令です。ここで使われているようにifは修飾語的な使い方もできます。
12行目で$LOCKINGにfalseを入れています。

今回は実際に実行できるものではありませんでしたがCGIなどのネットワーク上でプログラミングを行う際の処理をrubyでは簡単に行うことができることを示しています。
begin〜endについてはrubyのユーザーガイドにも丁寧に解説されていますのでそちらも参照しておいてください。
ユーザーガイドの例外処理


今回始めて使った命令など

| | メニュー戻る | |

LinkExchange Japan
LinkExchange Japan Member