Lock.java
001 package gate.creole.annic.apache.lucene.store;
002 
003 /**
004  * Copyright 2004 The Apache Software Foundation
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 
019 import gate.creole.annic.apache.lucene.index.IndexWriter;
020 
021 import java.io.IOException;
022 
023 /** An interprocess mutex lock.
024  <p>Typical use might look like:<pre>
025  * new Lock.With(directory.makeLock("my.lock")) {
026  *     public Object doBody() {
027  *       <i>... code to execute while locked ...</i>
028  *     }
029  *   }.run();
030  </pre>
031  *
032  @author Doug Cutting
033  @version $Id: Lock.java 529 2004-10-05 11:55:26Z niraj $
034  @see Directory#makeLock(String)
035  */
036 public abstract class Lock {
037   public static final long LOCK_POLL_INTERVAL = 1000;
038 
039   /** Attempts to obtain exclusive access and immediately return
040    *  upon success or failure.
041    @return true iff exclusive access is obtained
042    */
043   public abstract boolean obtain() throws IOException;
044 
045   /** Attempts to obtain an exclusive lock within amount
046    *  of time given. Currently polls once per second until
047    *  lockWaitTimeout is passed.
048    @param lockWaitTimeout length of time to wait in ms
049    @return true if lock was obtained
050    @throws IOException if lock wait times out or obtain() throws an IOException
051    */
052   public boolean obtain(long lockWaitTimeoutthrows IOException {
053     boolean locked = obtain();
054     int maxSleepCount = (int)(lockWaitTimeout / LOCK_POLL_INTERVAL);
055     int sleepCount = 0;
056     while (!locked) {
057       if (++sleepCount == maxSleepCount) {
058         throw new IOException("Lock obtain timed out: " this.toString());
059       }
060       try {
061         Thread.sleep(LOCK_POLL_INTERVAL);
062       catch (InterruptedException e) {
063         throw new IOException(e.toString());
064       }
065       locked = obtain();
066     }
067     return locked;
068   }
069 
070   /** Releases exclusive access. */
071   public abstract void release();
072 
073   /** Returns true if the resource is currently locked.  Note that one must
074    * still call {@link #obtain()} before using the resource. */
075   public abstract boolean isLocked();
076 
077 
078   /** Utility class for executing code with exclusive access. */
079   public abstract static class With {
080     private Lock lock;
081     private long lockWaitTimeout;
082 
083     /** Constructs an executor that will grab the named lock.
084      *  Defaults lockWaitTimeout to Lock.COMMIT_LOCK_TIMEOUT.
085      *  @deprecated Kept only to avoid breaking existing code.
086      */
087     @Deprecated
088     public With(Lock lock)
089     {
090       this(lock, IndexWriter.COMMIT_LOCK_TIMEOUT);
091     }
092 
093     /** Constructs an executor that will grab the named lock. */
094     public With(Lock lock, long lockWaitTimeout) {
095       this.lock = lock;
096       this.lockWaitTimeout = lockWaitTimeout;
097     }
098 
099     /** Code to execute with exclusive access. */
100     protected abstract Object doBody() throws IOException;
101 
102     /** Calls {@link #doBody} while <i>lock</i> is obtained.  Blocks if lock
103      * cannot be obtained immediately.  Retries to obtain lock once per second
104      * until it is obtained, or until it has tried ten times. Lock is released when
105      {@link #doBody} exits. */
106     public Object run() throws IOException {
107       boolean locked = false;
108       try {
109          locked = lock.obtain(lockWaitTimeout);
110          return doBody();
111       finally {
112         if (locked)
113         lock.release();
114       }
115     }
116   }
117 
118 }