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();
}
}