/* * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/** * A small helper class to help track clients which still * have pending operations at the end of a test.
*/ publicclass ReferenceTracker { privatefinal ConcurrentLinkedQueue<Tracker> TRACKERS
= new ConcurrentLinkedQueue<Tracker>();
publicstaticfinal ReferenceTracker INSTANCE
= new ReferenceTracker();
public Tracker getTracker(HttpClient client) { return OperationTrackers.getTracker(Objects.requireNonNull(client));
}
public AssertionError check(Tracker tracker, long graceDelayMs,
Predicate<Tracker> hasOutstanding,
String description, boolean printThreads) {
AssertionError fail = null;
graceDelayMs = Math.max(graceDelayMs, 100); long delay = Math.min(graceDelayMs, 10); var count = delay > 0 ? graceDelayMs / delay : 1; long waitStart = System.nanoTime(); long waited = 0; long toWait = Math.min(graceDelayMs, Math.max(delay, 1)); for (int i = 0; i < count; i++) { if (hasOutstanding.test(tracker)) {
System.gc(); try { if (i == 0) {
System.out.println("Waiting for HTTP operations to terminate...");
}
waited += toWait; Thread.sleep(toWait);
} catch (InterruptedException x) { // OK
}
} else {
System.out.println("No outstanding HTTP operations remaining after "
+ i + "/" + count + " iterations and " + waited + "/" + graceDelayMs
+ " ms, (wait/iteration " + toWait + " ms)"); break;
}
} long duration = Duration.ofNanos(System.nanoTime() - waitStart).toMillis(); if (hasOutstanding.test(tracker)) {
StringBuilder warnings = diagnose(tracker, new StringBuilder(), hasOutstanding); if (hasOutstanding.test(tracker)) {
fail = new AssertionError(warnings.toString());
}
} else {
System.out.println("PASSED: No " + description + " found in "
+ tracker.getName() + " in " + duration + " ms");
} if (fail != null) { if (printThreads && tracker.isSelectorAlive()) { var msg = "Selector manager threads are still alive for " + tracker.getName() + ": ";
printThreads(msg, System.out);
printThreads(msg, System.err);
}
System.out.println("AssertionError: Found some " + description + " in "
+ tracker.getName() + " after " + duration + " ms, waited " + waited + " ms");
} return fail;
}
public AssertionError check(long graceDelayMs,
Predicate<Tracker> hasOutstanding,
String description, boolean printThreads) {
AssertionError fail = null;
graceDelayMs = Math.max(graceDelayMs, 100); long delay = Math.min(graceDelayMs, 10); var count = delay > 0 ? graceDelayMs / delay : 1; for (int i = 0; i < count; i++) { if (TRACKERS.stream().anyMatch(hasOutstanding)) {
System.gc(); try { if (i == 0) {
System.out.println("Waiting for HTTP operations to terminate...");
} Thread.sleep(Math.min(graceDelayMs, Math.max(delay, 1)));
} catch (InterruptedException x) { // OK
}
} elsebreak;
} if (TRACKERS.stream().anyMatch(hasOutstanding)) {
StringBuilder warnings = diagnose(new StringBuilder(), hasOutstanding);
addSummary(warnings); if (TRACKERS.stream().anyMatch(hasOutstanding)) {
fail = new AssertionError(warnings.toString());
}
} else {
System.out.println("PASSED: No " + description + " found in "
+ getTrackedClientCount() + " clients");
} if (fail != null) {
Predicate<Tracker> isAlive = Tracker::isSelectorAlive; if (printThreads && TRACKERS.stream().anyMatch(isAlive)) {
printThreads("Some selector manager threads are still alive: ", System.out);
printThreads("Some selector manager threads are still alive: ", System.err);
}
} return fail;
}
privatevoid addSummary(StringBuilder warning) { long activeClients = getOutstandingClientCount(); long operations = getOutstandingOperationsCount(); long tracked = getTrackedClientCount(); if (warning.length() > 0) warning.append("\n"); int pos = warning.length();
warning.append("Found ")
.append(activeClients)
.append(" client still active, with ")
.append(operations)
.append(" operations still pending out of ")
.append(tracked)
.append(" tracked clients.");
System.out.println(warning.substring(pos));
System.err.println(warning.substring(pos));
}
privateboolean isSelectorManager(Thread t) {
String name = t.getName(); if (name == null) returnfalse; return name.contains("SelectorManager");
}
// This is a slightly more permissive check than the default checks, // it only verifies that all CFs returned by send/sendAsync have been // completed, and that all opened channels have been closed, and that // the selector manager thread has exited. // It doesn't check that all refcounts have reached 0. // This is typically useful to only check that resources have been released. public AssertionError checkShutdown(long graceDelayMs) {
Predicate<Tracker> isAlive = Tracker::isSelectorAlive;
Predicate<Tracker> hasPendingRequests = (t) -> t.getOutstandingHttpRequests() > 0;
Predicate<Tracker> hasPendingConnections = (t) -> t.getOutstandingTcpConnections() > 0;
Predicate<Tracker> hasPendingSubscribers = (t) -> t.getOutstandingSubscribers() > 0;
AssertionError failed = check(graceDelayMs,
isAlive.or(hasPendingRequests)
.or(hasPendingConnections)
.or(hasPendingSubscribers), "outstanding unclosed resources", true); return failed;
}
}
¤ Dauer der Verarbeitung: 0.44 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.