001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.kahadb.util; 018 019 import java.io.File; 020 import java.io.IOException; 021 import java.io.RandomAccessFile; 022 import java.nio.channels.FileLock; 023 import java.nio.channels.OverlappingFileLockException; 024 025 /** 026 * Used to lock a File. 027 * 028 * @author chirino 029 */ 030 public class LockFile { 031 032 private static final boolean DISABLE_FILE_LOCK = "true".equals(System.getProperty("java.nio.channels.FileLock.broken", "false")); 033 final private File file; 034 035 private FileLock lock; 036 private RandomAccessFile readFile; 037 private int lockCounter; 038 private final boolean deleteOnUnlock; 039 040 public LockFile(File file, boolean deleteOnUnlock) { 041 this.file = file; 042 this.deleteOnUnlock = deleteOnUnlock; 043 } 044 045 /** 046 * @throws IOException 047 */ 048 synchronized public void lock() throws IOException { 049 if (DISABLE_FILE_LOCK) { 050 return; 051 } 052 053 if( lockCounter>0 ) { 054 return; 055 } 056 057 IOHelper.mkdirs(file.getParentFile()); 058 059 if (lock == null) { 060 readFile = new RandomAccessFile(file, "rw"); 061 IOException reason = null; 062 try { 063 lock = readFile.getChannel().tryLock(); 064 } catch (OverlappingFileLockException e) { 065 reason = IOExceptionSupport.create("File '" + file + "' could not be locked.",e); 066 } 067 if (lock != null) { 068 lockCounter++; 069 } else { 070 // new read file for next attempt 071 closeReadFile(); 072 if (reason != null) { 073 throw reason; 074 } 075 throw new IOException("File '" + file + "' could not be locked."); 076 } 077 078 } 079 } 080 081 /** 082 */ 083 public void unlock() { 084 if (DISABLE_FILE_LOCK) { 085 return; 086 } 087 088 lockCounter--; 089 if( lockCounter!=0 ) { 090 return; 091 } 092 093 // release the lock.. 094 if (lock != null) { 095 try { 096 lock.release(); 097 } catch (Throwable ignore) { 098 } 099 lock = null; 100 } 101 closeReadFile(); 102 103 if( deleteOnUnlock ) { 104 file.delete(); 105 } 106 } 107 108 private void closeReadFile() { 109 // close the file. 110 if (readFile != null) { 111 try { 112 readFile.close(); 113 } catch (Throwable ignore) { 114 } 115 readFile = null; 116 } 117 118 } 119 120 }