/* * Copyright 2004 The Apache Software Foundation * * Licensed 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 IndexWriter = Lucene.Net.Index.IndexWriter; 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();
	/// 
/// ///
/// Doug Cutting /// /// $Id: Lock.cs,v 1.6 2005/10/31 00:37:06 dsd Exp $ /// /// /// public abstract class Lock { public static long LOCK_POLL_INTERVAL = 1000; /// Attempts to obtain exclusive access and immediately return /// upon success or failure. /// /// true iff exclusive access is obtained /// public abstract bool Obtain(); /// Attempts to obtain an exclusive lock within amount /// of time given. Currently polls once per second until /// lockWaitTimeout is passed. /// /// length of time to wait in ms /// /// true if lock was obtained /// /// IOException if lock wait times out or obtain() throws an IOException public virtual bool Obtain(long lockWaitTimeout) { int maxSleepCount = (int) (lockWaitTimeout / LOCK_POLL_INTERVAL); int sleepCount = 0; maxSleepCount = System.Math.Max (maxSleepCount, 1); FSDirectory.Log ("Lock.Obtain timeout={0} maxsleepcount={1}", lockWaitTimeout, maxSleepCount); bool locked = Obtain(); while (!locked) { if (sleepCount == maxSleepCount) { // Try and be a little more verbose on failure string lockpath = this.ToString (); System.Text.StringBuilder ex = new System.Text.StringBuilder(); ex.Append ("Lock obain timed out: "); ex.Append (lockpath); if (System.IO.File.Exists (lockpath)) { System.IO.FileStream fs = System.IO.File.Open (lockpath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); System.IO.StreamReader sr = new System.IO.StreamReader (fs); string pid = sr.ReadToEnd ().Trim (); sr.Close (); fs.Close (); ex.Append (" -- pid ").Append (pid); if (System.IO.Directory.Exists ("/proc/" + pid)) ex.Append (" -- process exists"); else ex.Append (" -- process does not exist, stale lockfile?"); } else { ex.Append (" -- lock file doesn't exist!?"); } throw new System.IO.IOException(ex.ToString ()); } ++sleepCount; System.Threading.Thread.Sleep((int) LOCK_POLL_INTERVAL); 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 {@link #Obtain()} 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. /// Defaults lockWaitTimeout to Lock.COMMIT_LOCK_TIMEOUT. /// /// Kept only to avoid breaking existing code. /// public With(Lock lock_Renamed):this(lock_Renamed, IndexWriter.COMMIT_LOCK_TIMEOUT) { } /// Constructs an executor that will grab the named lock. public With(Lock lock_Renamed, long lockWaitTimeout) { this.lock_Renamed = lock_Renamed; this.lockWaitTimeout = lockWaitTimeout; } /// Code to execute with exclusive access. public abstract System.Object DoBody(); /// Calls {@link #doBody} 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 /// {@link #doBody} exits. /// public virtual System.Object Run() { bool locked = false; try { locked = lock_Renamed.Obtain(lockWaitTimeout); return DoBody(); } finally { if (locked) lock_Renamed.Release(); } } } } }