Index: [Article Count Order] [Thread]

Date:  Tue, 3 Oct 2000 16:32:15 +0900
From:  tetsuya@....jp
Subject:  [XP-jp:01022] Re: ファイル	ロックユーティリティ
To:  extremeprogramming-jp@....jp (extremeprogramming-jp ML)
Message-Id:  <97BA340C0480D411BDA800062939A1890607C4@....jp>
Posted:  Tue, 3 Oct 2000 16:30:07 +0900 
X-Mail-Count: 01022

栗原です。

Nakamura Tadashi [mailto:Nakamura.Tadashi@....jp] wrote:

> > あう。誤解されています。
> ありゃ.

誤解をしているのが私のほうでなければ良いのですが(^_^;;
# プロセスは、それぞれ別のJVMと考えてください。

1. プロセスAがロックを取得
2. プロセスAがロックを開放(deleteOnExit付き)
3. プロセスBがロックを取得
4. プロセスAが終了することで、プロセスBのロックファイルを削除
5. プロセスBがロック中にも関わらず、プロセスCがロックを取得し
   ようとすると成功してしまう

こんな感じです。
実際に試したわけではないですが、File#deleteOnExit()の説明として、

この抽象パス名が示すファイルまたはディレクトリが、Virtual Machine
が終了したときに削除されるように要求します。削除は、Java 言語仕様
(12.9) で定義されているように、Virtual Machine が正常終了する場合
にだけ試行されます。 

とだけあるので、File#delete()が先に呼び出されていても、JVMが終了
した時点でもう一度ファイル削除が試行されるのではないでしょうか?
# 私の認識違いでしたら、ご指摘ください。

以下に、平鍋さんからの提案を取り入れた、統合バージョンの試作コー
ドを書いてみました。

/*
 * $Id$
 */
package XP.jp.co.esm.wiki.extremedomo.util;

import java.io.*;

public class FileLock {
    public FileLock(final String nameOfLockFile) {
        lockFile = new File(nameOfLockFile);
    }
    public void attempt()
        throws FileLockException {

        attempt(0);
    }
    public void attempt(final long milliSec)
        throws FileLockException {

        attemptCreateLockFile(milliSec);
        create = true;

        // ここで呼び出すということですよね?
        // 中村さん?
        // LockFile.deleteOnExit();
    }
    public void release() {
        if (!create)
            return;

        lockFile.delete();
    }
    private void attemptCreateLockFile(final long milliSec)
        throws FileLockException {

        try {
            if (lockFile.createNewFile())
                return;
            else if (milliSec <= 0)
                throw new AttemptTimeOutException();
            else {
                long startTime = System.currentTimeMillis();
                long retryTime = 0;

                while (true) {
                    Thread.currentThread().sleep(intervalTime);
                    if (lockFile.createNewFile())
                        return;
                    else {
                        long nowTime = System.currentTimeMillis();
                        retryTime += nowTime - startTime;
                        if (milliSec < retryTime)
                            throw new AttemptTimeOutException();
                    }
                }
            }
        } catch (IOException e) {
            throw new FileLockException(e.toString());
        } catch (InterruptedException e) {
            throw new FileLockException(e.toString());
        }
    }

    private final File lockFile;
    private final long intervalTime = 50;
    private boolean create = false;
}

---
Tetsuya Kurihara
tetsuya@....jp