2 * inter-VM file locking
\r
4 * Copyright(c) 2009 olyutorskii
\r
5 * $Id: InterVMLock.java 952 2009-12-06 14:29:10Z olyutorskii $
\r
8 package jp.sourceforge.jindolf;
\r
10 import java.io.File;
\r
11 import java.io.FileNotFoundException;
\r
12 import java.io.FileOutputStream;
\r
13 import java.io.IOException;
\r
14 import java.util.Collections;
\r
15 import java.util.HashSet;
\r
16 import java.util.Set;
\r
19 * ロックファイルを用いたVM間ロックオブジェクト。
\r
20 * 大昔のNFSではうまく動かないかも。
\r
21 * 一度でもロックに成功したロックファイルはVM終了時に消されてしまうので注意。
\r
23 public class InterVMLock{
\r
25 /** 所持するロックオブジェクト一覧。 */
\r
26 private static final Set<InterVMLock> ownedLockSet =
\r
27 Collections.synchronizedSet(new HashSet<InterVMLock>());
\r
30 Runtime runtime = Runtime.getRuntime();
\r
31 runtime.addShutdownHook(new Thread(){
\r
32 @Override public void run(){ clearOwnedLockSet(); }
\r
37 * 所持するロックオブジェクト一覧への登録。
\r
38 * @param lock 登録するロックオブジェクト
\r
40 private static void addOwnedLock(InterVMLock lock){
\r
41 synchronized(ownedLockSet){
\r
42 if( ! lock.isFileOwner() ) return;
\r
43 ownedLockSet.add(lock);
\r
44 lock.getLockFile().deleteOnExit();
\r
50 * 所持するロックオブジェクト一覧からの脱退。
\r
51 * @param lock 脱退対象のロックオブジェクト
\r
53 private static void removeOwnedLock(InterVMLock lock){
\r
54 synchronized(ownedLockSet){
\r
55 ownedLockSet.remove(lock);
\r
61 * 所持するロックオブジェクトすべてを解放しロックファイルを削除する。
\r
63 private static void clearOwnedLockSet(){
\r
64 synchronized(ownedLockSet){
\r
65 for(InterVMLock lock : ownedLockSet){
\r
66 if( ! lock.isFileOwner() ) continue;
\r
69 lock.getLockFile().delete();
\r
70 }catch(SecurityException e){
\r
74 ownedLockSet.clear();
\r
80 private final File lockFile;
\r
81 private boolean isFileOwner = false;
\r
82 private FileOutputStream stream = null;
\r
86 * この時点ではまだロックファイルの存在は確認されない。
\r
87 * @param lockFile ロックファイル
\r
88 * @throws NullPointerException 引数がnull
\r
90 public InterVMLock(File lockFile) throws NullPointerException{
\r
91 if(lockFile == null) throw new NullPointerException();
\r
92 this.lockFile = lockFile;
\r
100 public File getLockFile(){
\r
101 return this.lockFile;
\r
105 * ロックファイルがディスク上に存在するか判定する。
\r
106 * @return 存在すればtrue
\r
108 public boolean isExistsFile(){
\r
109 if(this.lockFile.exists()){
\r
116 * このオブジェクトがロックファイルの作者であるか判定する。
\r
119 public synchronized boolean isFileOwner(){
\r
120 return this.isFileOwner;
\r
124 * ロックファイルのオープン中のストリームを返す。
\r
125 * ※ 排他制御目的のリソースなので、
\r
126 * 勝手に書き込んだりクローズしたりしないように。
\r
127 * @return オープン中のストリーム。オープンしてなければnull
\r
129 protected synchronized FileOutputStream getOpenedStream(){
\r
130 if(isFileOwner()) return this.stream;
\r
135 * ロックファイルの強制削除を試みる。
\r
136 * @return 強制削除に成功すればtrue
\r
138 public synchronized boolean forceRemove(){
\r
139 if(isFileOwner()) release();
\r
141 if( ! isExistsFile() ) return true;
\r
144 boolean result = this.lockFile.delete();
\r
145 if( ! result ) return false;
\r
146 }catch(SecurityException e){
\r
150 if(isExistsFile()) return false;
\r
157 * 生成されるロックファイルはVM終了時に削除されるよう登録される。
\r
158 * このメソッド実行中にVM終了が重なると、
\r
159 * ロックファイルが正しく削除されない場合がありうる。
\r
160 * @return 成功すればtrue
\r
162 protected synchronized boolean touchLockFile(){
\r
163 boolean result = false;
\r
165 result = this.lockFile.createNewFile();
\r
166 }catch(IOException e){
\r
168 }catch(SecurityException e){
\r
171 if(result == false){
\r
176 this.isFileOwner = true;
\r
177 this.stream = new FileOutputStream(this.lockFile);
\r
178 }catch(FileNotFoundException e){
\r
180 this.isFileOwner = false;
\r
181 this.stream = null;
\r
183 this.lockFile.delete();
\r
184 }catch(SecurityException e2){
\r
190 addOwnedLock(this);
\r
198 * @return すでにロック済みもしくはロックに成功すればtrue
\r
200 public synchronized boolean tryLock(){
\r
201 if( isFileOwner() ) return true;
\r
203 if(isExistsFile()) return false;
\r
204 if(touchLockFile() != true) return false;
\r
211 * 自分が作者であるロックファイルは閉じられ削除される。
\r
214 public synchronized void release(){
\r
215 if( ! isFileOwner() ) return;
\r
218 this.stream.close();
\r
219 }catch(IOException e){
\r
222 this.stream = null;
\r
224 this.lockFile.delete();
\r
225 }catch(SecurityException e){
\r
228 removeOwnedLock(this);
\r
229 this.isFileOwner = false;
\r