You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dw...@apache.org on 2014/06/06 08:10:25 UTC

svn commit: r1600813 - in /lucene/dev/branches/LUCENE-5716/lucene: core/src/test/org/apache/lucene/ test-framework/ test-framework/src/aspects/META-INF/ test-framework/src/aspects/com/ test-framework/src/aspects/com/carrotsearch/ test-framework/src/asp...

Author: dweiss
Date: Fri Jun  6 06:10:25 2014
New Revision: 1600813

URL: http://svn.apache.org/r1600813
Log:
Adding proper FileInputStream tracking, assertions and some verbose info.

Added:
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/FileInputStreamTracker.aj
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/Tracker.aj
Modified:
    lucene/dev/branches/LUCENE-5716/lucene/core/src/test/org/apache/lucene/TestSearch.java
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/build.xml
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/META-INF/aop-ajc.xml
    lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/org/apache/lucene/util/NoDescriptorLeaksAspect.aj

Modified: lucene/dev/branches/LUCENE-5716/lucene/core/src/test/org/apache/lucene/TestSearch.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-5716/lucene/core/src/test/org/apache/lucene/TestSearch.java?rev=1600813&r1=1600812&r2=1600813&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-5716/lucene/core/src/test/org/apache/lucene/TestSearch.java (original)
+++ lucene/dev/branches/LUCENE-5716/lucene/core/src/test/org/apache/lucene/TestSearch.java Fri Jun  6 06:10:25 2014
@@ -20,6 +20,7 @@ package org.apache.lucene;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
+import java.io.FileInputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 

Modified: lucene/dev/branches/LUCENE-5716/lucene/test-framework/build.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-5716/lucene/test-framework/build.xml?rev=1600813&r1=1600812&r2=1600813&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-5716/lucene/test-framework/build.xml (original)
+++ lucene/dev/branches/LUCENE-5716/lucene/test-framework/build.xml Fri Jun  6 06:10:25 2014
@@ -50,7 +50,8 @@
   	<aspectj:iajc 
   		sourceRoots="src/aspects"
   		outJar="${build.dir}/aspects.jar"
-  		sourceRootCopyFilter="**/*.java,**/*.aj">
+  		sourceRootCopyFilter="**/*.java,**/*.aj"
+  		source="1.7">
   	  <classpath location="${build.dir}/classes/java" />
   	  <classpath refid="classpath" />
   	</aspectj:iajc>

Modified: lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/META-INF/aop-ajc.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/META-INF/aop-ajc.xml?rev=1600813&r1=1600812&r2=1600813&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/META-INF/aop-ajc.xml (original)
+++ lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/META-INF/aop-ajc.xml Fri Jun  6 06:10:25 2014
@@ -1,6 +1,8 @@
 <aspectj>
   <aspects>
     <aspect name="org.apache.lucene.util.NoDescriptorLeaksAspect" />
+
+    <aspect name="com.carrotsearch.aspects.FileInputStreamTracker" />
   </aspects>
 
   <weaver options="-XnoInline -Xlint:ignore" />

Added: lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/FileInputStreamTracker.aj
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/FileInputStreamTracker.aj?rev=1600813&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/FileInputStreamTracker.aj (added)
+++ lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/FileInputStreamTracker.aj Fri Jun  6 06:10:25 2014
@@ -0,0 +1,97 @@
+package com.carrotsearch.aspects;
+
+import static com.carrotsearch.aspects.Tracker.isTracking;
+import static com.carrotsearch.aspects.Tracker.track;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import org.apache.lucene.util.LuceneTestCase;
+
+/** */
+public aspect FileInputStreamTracker {
+  /** */
+  public final class Delegate extends FileInputStream {
+    private String path;
+    
+    public Delegate(File file) throws FileNotFoundException {
+      super(file);
+      if (LuceneTestCase.VERBOSE) System.out.println("Opening FIS(" + file.getAbsolutePath() + ")");
+      this.path = file.getAbsolutePath();
+    }
+
+    public Delegate(String path) throws FileNotFoundException { 
+      super(path);
+      if (LuceneTestCase.VERBOSE) System.out.println("Opening FIS(" + path + ")");
+      this.path = path;
+    }
+
+    public Delegate(FileDescriptor fd) { 
+      super(fd);
+      if (LuceneTestCase.VERBOSE) System.out.println("Opening FIS(" + fd + ")");
+      this.path = "[FileDescriptor constructor]";
+    }
+
+    @Override
+    public void close() throws IOException {
+      // TODO: Mark as closed, even if an exception occurs in real close()?
+      super.close();
+      Tracker.close(this);
+    }
+    
+    @Override
+    protected void finalize() throws IOException {
+      // We do not rely in finalize() closing the stream, so close the actual
+      // stream, but do NOT mark it as properly closed.
+      super.close();
+    }
+    
+    @Override
+    public String toString() {
+      return "FileInputStream(" + path + ")";
+    }
+  }
+
+  /** */
+  FileInputStream around(File file) throws FileNotFoundException: 
+    call(FileInputStream.new(File) throws FileNotFoundException) && 
+    args(file)
+  {
+    return isTracking() ? track(new Delegate(file)) : proceed(file);
+  }
+  
+  /** */
+  FileInputStream around(String path) throws FileNotFoundException: 
+    call(FileInputStream.new(String) throws FileNotFoundException) && 
+    args(path)
+  {
+    return isTracking() ? track(new Delegate(path)) : proceed(path);
+  }
+
+  /** */
+  FileInputStream around(FileDescriptor fd): 
+    call(FileInputStream.new(FileDescriptor)) && 
+    args(fd)
+  {
+    return isTracking() ? track(new Delegate(fd)) : proceed(fd);
+  }
+
+  /** 
+   * Tracking any other classes inheriting from FileInputStream is tricky because we don't know
+   * their code; we'd need to make sure they override close() and finalize() so that we can 
+   * advise the code!
+   * 
+   * For now, just ban such classes at runtime (prevent instantiation).
+   */
+  before():
+    !within(com.carrotsearch.aspects.**) &&
+    execution(FileInputStream+.new(..)) {
+    try {
+      ((FileInputStream) thisJoinPoint.getTarget()).close();
+    } catch (IOException e) {/* Try to close the super, we can't inject before it. */}
+    throw new UnsupportedOperationException("FileInputStream not supported for classes that inherit from FileInputStream.");
+  }
+}

Added: lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/Tracker.aj
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/Tracker.aj?rev=1600813&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/Tracker.aj (added)
+++ lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/com/carrotsearch/aspects/Tracker.aj Fri Jun  6 06:10:25 2014
@@ -0,0 +1,102 @@
+package com.carrotsearch.aspects;
+
+import java.util.*;
+
+public class Tracker {
+  public static class TrackingInfo {
+    public final Object target;
+    public volatile boolean closed;
+
+    TrackingInfo(Object target, boolean closed) {
+      this.target = target;
+      this.closed = closed;
+    }
+    
+    @Override
+    public String toString() {
+      return "FH: " + target + " [" + (closed ? "closed" : "open") + "]";
+    }
+  }
+
+  public static class TrackingStats {
+    public final Map<Object, TrackingInfo> open = new HashMap<>();
+    public final Map<Object, TrackingInfo> closed = new HashMap<>();
+  }
+
+  private static final Object lock = new Object();
+
+  /** Guarded by: {@link #lock}. */
+  private static boolean tracking;
+  private static IdentityHashMap<Object, TrackingInfo> trackpool = new IdentityHashMap<>();
+
+  /**
+   * Start tracking resources.
+   */
+  public static void startTracking() {
+    synchronized (lock) {
+      tracking = true;
+    }
+  }
+
+  /**
+   * Stop tracking resources.
+   */
+  public static void endTracking() {
+    synchronized (lock) {
+      tracking = false;
+    }
+  }
+
+  /**
+   * Clear currently tracked resources.
+   */
+  public static void reset() {
+    synchronized (lock) {
+      trackpool.clear();
+    }
+  }
+
+  public static TrackingStats snapshot() {
+    synchronized (lock) {
+      TrackingStats stats = new TrackingStats();
+      for (TrackingInfo ti : trackpool.values()) {
+        if (ti.closed) {
+          stats.closed.put(ti.target, ti);
+        } else {
+          stats.open.put(ti.target, ti);
+        }
+      }
+      return stats;
+    }
+  }
+
+  /**
+   * Are we tracking open/ close calls?
+   */
+  static final boolean isTracking() {
+    return tracking;
+  }
+
+  /**
+   * Start tracking object (instantiated).
+   */
+  static final <T> T track(T target) {
+    synchronized (lock) {
+      assert !trackpool.containsKey(target);
+      trackpool.put(target, new TrackingInfo(target, false));
+    }
+    return target;
+  }
+
+  /**
+   * Tracked object's close method called.
+   */
+  static final void close(Object target) {
+    synchronized (lock) {
+      final TrackingInfo trackingInfo = trackpool.get(target);
+      if (trackingInfo != null) {
+        trackingInfo.closed = true;
+      }
+    }
+  }
+}

Modified: lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/org/apache/lucene/util/NoDescriptorLeaksAspect.aj
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/org/apache/lucene/util/NoDescriptorLeaksAspect.aj?rev=1600813&r1=1600812&r2=1600813&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/org/apache/lucene/util/NoDescriptorLeaksAspect.aj (original)
+++ lucene/dev/branches/LUCENE-5716/lucene/test-framework/src/aspects/org/apache/lucene/util/NoDescriptorLeaksAspect.aj Fri Jun  6 06:10:25 2014
@@ -17,14 +17,53 @@ package org.apache.lucene.util;
  * limitations under the License.
  */
 
+import com.carrotsearch.aspects.*;
+import com.carrotsearch.aspects.Tracker.TrackingInfo;
+import com.carrotsearch.aspects.Tracker.TrackingStats;
+
+import java.io.*;
+import java.util.Locale;
+
 public aspect NoDescriptorLeaksAspect {
   void around(): execution(void org.apache.lucene.util.TestRuleAspectJAspects.pointcutBeforeSuite(..)) {
-    System.out.println("## Before rule!");
+    Tracker.startTracking();
     proceed();
   }
   
   void around(): execution(void org.apache.lucene.util.TestRuleAspectJAspects.pointcutAfterSuite(..)) {
-    System.out.println("## After rule!");
+    TrackingStats stats = Tracker.snapshot();
+
+    // Close any unclosed resources.
+    for (Object o : stats.open.keySet()) {
+      try {
+        ((Closeable) o).close();
+      } catch (IOException e) {
+        // Ignore if we cannot close it.
+      }
+    }
+
+    // Disable tracking and reset tracking buffers.
+    Tracker.endTracking();
+    Tracker.reset();
+
+    // Verify assertions.
+    System.out.println(String.format(Locale.ENGLISH, 
+        "Tracked %d objects, %d closed, %d open.",
+        stats.closed.size() + stats.open.size(),
+        stats.closed.size(),
+        stats.open.size()));
+    
+    for (TrackingInfo i : stats.closed.values()) {
+      System.out.println(i);
+    }
+    for (TrackingInfo i : stats.open.values()) {
+      System.out.println(i);
+    }
+    
+    if (!stats.open.isEmpty()) {
+      throw new AssertionError("Unclosed file handles: " + stats.open.values());
+    }
+
     proceed();
   }  
 }