/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using Lucene.Net.Support; namespace Lucene.Net.Store { /// An interprocess mutex lock. ///

Typical use might look like: /// new Lock.With(directory.makeLock("my.lock")) { /// public Object doBody() { /// ... code to execute while locked ... /// } /// }.run(); /// ///

/// public abstract class Lock { /// How long waits, in milliseconds, /// in between attempts to acquire the lock. /// public static long LOCK_POLL_INTERVAL = 1000; /// Pass this value to to try /// forever to obtain the lock. /// public const long LOCK_OBTAIN_WAIT_FOREVER = - 1; /// Attempts to obtain exclusive access and immediately return /// upon success or failure. /// /// true iff exclusive access is obtained /// public abstract bool Obtain(); /// If a lock obtain called, this failureReason may be set /// with the "root cause" Exception as to why the lock was /// not obtained. /// protected internal System.Exception failureReason; /// Attempts to obtain an exclusive lock within amount of /// time given. Polls once per /// (currently 1000) milliseconds until lockWaitTimeout is /// passed. /// /// length of time to wait in /// milliseconds or /// to retry forever /// /// true if lock was obtained /// /// LockObtainFailedException if lock wait times out /// IllegalArgumentException if lockWaitTimeout is /// out of bounds /// /// IOException if obtain() throws IOException public virtual bool Obtain(long lockWaitTimeout) { failureReason = null; bool locked = Obtain(); if (lockWaitTimeout < 0 && lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER) throw new System.ArgumentException("lockWaitTimeout should be LOCK_OBTAIN_WAIT_FOREVER or a non-negative number (got " + lockWaitTimeout + ")"); long maxSleepCount = lockWaitTimeout / LOCK_POLL_INTERVAL; long sleepCount = 0; while (!locked) { if (lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER && sleepCount++ >= maxSleepCount) { System.String reason = "Lock obtain timed out: " + this.ToString(); if (failureReason != null) { reason += (": " + failureReason); } var e = failureReason != null ? new LockObtainFailedException(reason, failureReason) : new LockObtainFailedException(reason); throw e; } try { System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(LOCK_POLL_INTERVAL)); } catch (System.Threading.ThreadInterruptedException) { throw; } locked = Obtain(); } return locked; } /// Releases exclusive access. public abstract void Release(); /// Returns true if the resource is currently locked. Note that one must /// still call before using the resource. /// public abstract bool IsLocked(); /// Utility class for executing code with exclusive access. public abstract class With { private Lock lock_Renamed; private long lockWaitTimeout; /// Constructs an executor that will grab the named lock. protected With(Lock lock_Renamed, long lockWaitTimeout) { this.lock_Renamed = lock_Renamed; this.lockWaitTimeout = lockWaitTimeout; } /// Code to execute with exclusive access. protected internal abstract System.Object DoBody(); /// Calls while lock is obtained. Blocks if lock /// cannot be obtained immediately. Retries to obtain lock once per second /// until it is obtained, or until it has tried ten times. Lock is released when /// exits. /// /// LockObtainFailedException if lock could not /// be obtained /// /// IOException if throws IOException public virtual System.Object run() { bool locked = false; try { locked = lock_Renamed.Obtain(lockWaitTimeout); return DoBody(); } finally { if (locked) lock_Renamed.Release(); } } } } }