You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2015/05/30 08:22:07 UTC

svn commit: r1682582 - in /lucene/dev/branches/lucene6508/lucene/core/src: java/org/apache/lucene/index/ java/org/apache/lucene/store/ test/org/apache/lucene/index/ test/org/apache/lucene/store/

Author: rmuir
Date: Sat May 30 06:22:07 2015
New Revision: 1682582

URL: http://svn.apache.org/r1682582
Log:
add back write.lock timeout (we can change default to 0 if we want/deprecate/whatever)

Added:
    lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/store/SleepingLockWrapper.java   (with props)
    lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockWrapper.java
      - copied, changed from r1682579, lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockFactory.java
Removed:
    lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockFactory.java
Modified:
    lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
    lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java
    lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/LiveIndexWriterConfig.java
    lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterConfig.java

Modified: lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java?rev=1682582&r1=1682581&r2=1682582&view=diff
==============================================================================
--- lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (original)
+++ lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java Sat May 30 06:22:07 2015
@@ -59,6 +59,7 @@ import org.apache.lucene.store.Lock;
 import org.apache.lucene.store.LockObtainFailedException;
 import org.apache.lucene.store.MergeInfo;
 import org.apache.lucene.store.RateLimitedIndexOutput;
+import org.apache.lucene.store.SleepingLockWrapper;
 import org.apache.lucene.store.TrackingDirectoryWrapper;
 import org.apache.lucene.store.LockValidatingDirectoryWrapper;
 import org.apache.lucene.util.Accountable;
@@ -753,8 +754,18 @@ public class IndexWriter implements Clos
   public IndexWriter(Directory d, IndexWriterConfig conf) throws IOException {
     conf.setIndexWriter(this); // prevent reuse by other instances
     config = conf;
-
-    writeLock = d.obtainLock(WRITE_LOCK_NAME);
+    
+    // obtain the write.lock
+    long timeout = config.getWriteLockTimeout();
+    final Directory lockDir;
+    if (timeout == 0) {
+      // user doesn't want sleep/retries
+      lockDir = d;
+    } else {
+      lockDir = new SleepingLockWrapper(d, timeout);
+    }
+    writeLock = lockDir.obtainLock(WRITE_LOCK_NAME);
+    
     directory = d;
     // nocommit: turn on carefully after we get other stuff going
     // validatingDirectory = new LockValidatingDirectoryWrapper(d, writeLock);

Modified: lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java?rev=1682582&r1=1682581&r2=1682582&view=diff
==============================================================================
--- lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java (original)
+++ lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/IndexWriterConfig.java Sat May 30 06:22:07 2015
@@ -86,6 +86,13 @@ public final class IndexWriterConfig ext
    */
   public final static double DEFAULT_RAM_BUFFER_SIZE_MB = 16.0;
 
+  /**
+   * Default value for the write lock timeout (1,000 ms).
+   *
+   * @see #setDefaultWriteLockTimeout(long)
+   */
+  public static long WRITE_LOCK_TIMEOUT = 1000;
+
   /** Default setting for {@link #setReaderPooling}. */
   public final static boolean DEFAULT_READER_POOLING = false;
 
@@ -106,6 +113,24 @@ public final class IndexWriterConfig ext
   /** Default value for whether calls to {@link IndexWriter#close()} include a commit. */
   public final static boolean DEFAULT_COMMIT_ON_CLOSE = true;
   
+  /**
+   * Sets the default (for any instance) maximum time to wait for a write lock
+   * (in milliseconds).
+   */
+  public static void setDefaultWriteLockTimeout(long writeLockTimeout) {
+    WRITE_LOCK_TIMEOUT = writeLockTimeout;
+  }
+  
+  /**
+   * Returns the default write lock timeout for newly instantiated
+   * IndexWriterConfigs.
+   *
+   * @see #setDefaultWriteLockTimeout(long)
+   */
+  public static long getDefaultWriteLockTimeout() {
+    return WRITE_LOCK_TIMEOUT;
+  }
+  
   // indicates whether this config instance is already attached to a writer.
   // not final so that it can be cloned properly.
   private SetOnce<IndexWriter> writer = new SetOnce<>();
@@ -236,7 +261,24 @@ public final class IndexWriterConfig ext
   public MergeScheduler getMergeScheduler() {
     return mergeScheduler;
   }
+  
+  /**
+   * Sets the maximum time to wait for a write lock (in milliseconds) for this
+   * instance. You can change the default value for all instances by calling
+   * {@link #setDefaultWriteLockTimeout(long)}. Note that the value can be zero,
+   * for no sleep/retry behavior.
+   *
+   * <p>Only takes effect when IndexWriter is first created. */
+  public IndexWriterConfig setWriteLockTimeout(long writeLockTimeout) {
+    this.writeLockTimeout = writeLockTimeout;
+    return this;
+  }
 
+  @Override
+  public long getWriteLockTimeout() {
+    return writeLockTimeout;
+  }
+  
   /**
    * Set the {@link Codec}.
    * 

Modified: lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/LiveIndexWriterConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/LiveIndexWriterConfig.java?rev=1682582&r1=1682581&r2=1682582&view=diff
==============================================================================
--- lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/LiveIndexWriterConfig.java (original)
+++ lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/index/LiveIndexWriterConfig.java Sat May 30 06:22:07 2015
@@ -60,6 +60,9 @@ public class LiveIndexWriterConfig {
   /** {@link MergeScheduler} to use for running merges. */
   protected volatile MergeScheduler mergeScheduler;
 
+  /** Timeout when trying to obtain the write lock on init. */
+  protected volatile long writeLockTimeout;
+
   /** {@link IndexingChain} that determines how documents are
    *  indexed. */
   protected volatile IndexingChain indexingChain;
@@ -107,6 +110,7 @@ public class LiveIndexWriterConfig {
     openMode = OpenMode.CREATE_OR_APPEND;
     similarity = IndexSearcher.getDefaultSimilarity();
     mergeScheduler = new ConcurrentMergeScheduler();
+    writeLockTimeout = IndexWriterConfig.WRITE_LOCK_TIMEOUT;
     indexingChain = DocumentsWriterPerThread.defaultIndexingChain;
     codec = Codec.getDefault();
     if (codec == null) {
@@ -347,6 +351,15 @@ public class LiveIndexWriterConfig {
     return mergeScheduler;
   }
   
+  /**
+   * Returns allowed timeout when acquiring the write lock.
+   *
+   * @see IndexWriterConfig#setWriteLockTimeout(long)
+   */
+  public long getWriteLockTimeout() {
+    return writeLockTimeout;
+  }
+  
   /** Returns the current {@link Codec}. */
   public Codec getCodec() {
     return codec;
@@ -468,6 +481,8 @@ public class LiveIndexWriterConfig {
     sb.append("openMode=").append(getOpenMode()).append("\n");
     sb.append("similarity=").append(getSimilarity().getClass().getName()).append("\n");
     sb.append("mergeScheduler=").append(getMergeScheduler()).append("\n");
+    sb.append("default WRITE_LOCK_TIMEOUT=").append(IndexWriterConfig.WRITE_LOCK_TIMEOUT).append("\n");
+    sb.append("writeLockTimeout=").append(getWriteLockTimeout()).append("\n");
     sb.append("codec=").append(getCodec()).append("\n");
     sb.append("infoStream=").append(getInfoStream().getClass().getName()).append("\n");
     sb.append("mergePolicy=").append(getMergePolicy()).append("\n");

Added: lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/store/SleepingLockWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/store/SleepingLockWrapper.java?rev=1682582&view=auto
==============================================================================
--- lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/store/SleepingLockWrapper.java (added)
+++ lucene/dev/branches/lucene6508/lucene/core/src/java/org/apache/lucene/store/SleepingLockWrapper.java Sat May 30 06:22:07 2015
@@ -0,0 +1,109 @@
+package org.apache.lucene.store;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.util.ThreadInterruptedException;
+
+/** 
+ * Directory that wraps another, and that sleeps and retries
+ * if obtaining the lock fails.
+ * <p>
+ * This is not a good idea.
+ */
+public final class SleepingLockWrapper extends FilterDirectory {
+ 
+  /** 
+   * Pass this lockWaitTimeout to try forever to obtain the lock. 
+   */
+  public static final long LOCK_OBTAIN_WAIT_FOREVER = -1;
+  
+  /** 
+   * How long {@link #obtainLock} waits, in milliseconds,
+   * in between attempts to acquire the lock. 
+   */
+  public static long DEFAULT_POLL_INTERVAL = 1000;
+  
+  private final long lockWaitTimeout;
+  private final long pollInterval;
+  
+  /**
+   * Create a new SleepingLockFactory
+   * @param delegate        underlying directory to wrap
+   * @param lockWaitTimeout length of time to wait in milliseconds 
+   *                        or {@link #LOCK_OBTAIN_WAIT_FOREVER} to retry forever.
+   */
+  public SleepingLockWrapper(Directory delegate, long lockWaitTimeout) {
+    this(delegate, lockWaitTimeout, DEFAULT_POLL_INTERVAL);
+  }
+  
+  /**
+   * Create a new SleepingLockFactory
+   * @param delegate        underlying directory to wrap
+   * @param lockWaitTimeout length of time to wait in milliseconds 
+   *                        or {@link #LOCK_OBTAIN_WAIT_FOREVER} to retry forever.
+   * @param pollInterval    poll once per this interval in milliseconds until
+   *                        {@code lockWaitTimeout} is exceeded.
+   */
+  public SleepingLockWrapper(Directory delegate, long lockWaitTimeout, long pollInterval) {
+    super(delegate);
+    this.lockWaitTimeout = lockWaitTimeout;
+    this.pollInterval = pollInterval;
+    if (lockWaitTimeout < 0 && lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER) {
+      throw new IllegalArgumentException("lockWaitTimeout should be LOCK_OBTAIN_WAIT_FOREVER or a non-negative number (got " + lockWaitTimeout + ")");
+    }
+    if (pollInterval < 0) {
+      throw new IllegalArgumentException("pollInterval must be a non-negative number (got " + pollInterval + ")");
+    }
+  }
+
+  @Override
+  public Lock obtainLock(String lockName) throws IOException {
+    LockObtainFailedException failureReason = null;
+    long maxSleepCount = lockWaitTimeout / pollInterval;
+    long sleepCount = 0;
+    
+    do {
+      try {
+        return in.obtainLock(lockName);
+      } catch (LockObtainFailedException failed) {
+        if (failureReason == null) {
+          failureReason = failed;
+        }
+      }
+      try {
+        Thread.sleep(pollInterval);
+      } catch (InterruptedException ie) {
+        throw new ThreadInterruptedException(ie);
+      }
+    } while (sleepCount++ < maxSleepCount || lockWaitTimeout == LOCK_OBTAIN_WAIT_FOREVER);
+    
+    // we failed to obtain the lock in the required time
+    String reason = "Lock obtain timed out: " + this.toString();
+    if (failureReason != null) {
+      reason += ": " + failureReason;
+    }
+    throw new LockObtainFailedException(reason, failureReason);
+  }
+
+  @Override
+  public String toString() {
+    return "SleepingLockWrapper(" + in + ")";
+  }
+}

Modified: lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterConfig.java?rev=1682582&r1=1682581&r2=1682582&view=diff
==============================================================================
--- lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterConfig.java (original)
+++ lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterConfig.java Sat May 30 06:22:07 2015
@@ -63,6 +63,8 @@ public class TestIndexWriterConfig exten
     assertEquals(OpenMode.CREATE_OR_APPEND, conf.getOpenMode());
     // we don't need to assert this, it should be unspecified
     assertTrue(IndexSearcher.getDefaultSimilarity() == conf.getSimilarity());
+    assertEquals(IndexWriterConfig.getDefaultWriteLockTimeout(), conf.getWriteLockTimeout());
+    assertEquals(IndexWriterConfig.WRITE_LOCK_TIMEOUT, IndexWriterConfig.getDefaultWriteLockTimeout());
     assertEquals(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DELETE_TERMS, conf.getMaxBufferedDeleteTerms());
     assertEquals(IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB, conf.getRAMBufferSizeMB(), 0.0);
     assertEquals(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS, conf.getMaxBufferedDocs());
@@ -177,6 +179,7 @@ public class TestIndexWriterConfig exten
   @Test
   public void testConstants() throws Exception {
     // Tests that the values of the constants does not change
+    assertEquals(1000, IndexWriterConfig.WRITE_LOCK_TIMEOUT);
     assertEquals(-1, IndexWriterConfig.DISABLE_AUTO_FLUSH);
     assertEquals(IndexWriterConfig.DISABLE_AUTO_FLUSH, IndexWriterConfig.DEFAULT_MAX_BUFFERED_DELETE_TERMS);
     assertEquals(IndexWriterConfig.DISABLE_AUTO_FLUSH, IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS);

Copied: lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockWrapper.java (from r1682579, lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockFactory.java)
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockWrapper.java?p2=lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockWrapper.java&p1=lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockFactory.java&r1=1682579&r2=1682582&rev=1682582&view=diff
==============================================================================
--- lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockFactory.java (original)
+++ lucene/dev/branches/lucene6508/lucene/core/src/test/org/apache/lucene/store/TestSleepingLockWrapper.java Sat May 30 06:22:07 2015
@@ -22,8 +22,8 @@ import java.nio.file.Path;
 
 import org.apache.lucene.util.TestUtil;
 
-/** Simple tests for SleepingLockFactory */
-public class TestSleepingLockFactory extends BaseLockFactoryTestCase {
+/** Simple tests for SleepingLockWrapper */
+public class TestSleepingLockWrapper extends BaseLockFactoryTestCase {
 
   @Override
   protected Directory getDirectory(Path path) throws IOException {
@@ -33,11 +33,11 @@ public class TestSleepingLockFactory ext
     int which = random().nextInt(3);
     switch (which) {
       case 0:
-        return newDirectory(random(), new SleepingLockFactory(new SingleInstanceLockFactory(), lockWaitTimeout, pollInterval));
+        return new SleepingLockWrapper(newDirectory(random(), new SingleInstanceLockFactory()), lockWaitTimeout, pollInterval);
       case 1:
-        return newFSDirectory(path, new SleepingLockFactory(NativeFSLockFactory.INSTANCE, lockWaitTimeout, pollInterval));
+        return new SleepingLockWrapper(newFSDirectory(path), lockWaitTimeout, pollInterval);
       default:
-        return newFSDirectory(path, new SleepingLockFactory(SimpleFSLockFactory.INSTANCE, lockWaitTimeout, pollInterval));
+        return new SleepingLockWrapper(newFSDirectory(path), lockWaitTimeout, pollInterval);
     }
   }