move the connections closing to a separate threadpool and limit the time we wait for reset() to complete

pull/24/head
Zlatin Balevsky 2019-10-29 09:01:41 +00:00
parent 6c806c4441
commit d7c7afe2c0
5 changed files with 31 additions and 10 deletions

View File

@ -353,6 +353,7 @@ public class Core {
log.info("shutting down embedded router")
router.shutdown(0)
}
log.info("shutdown complete")
}
static main(args) {

View File

@ -1,7 +1,12 @@
package com.muwire.core.connection
import java.util.concurrent.BlockingQueue
import java.util.concurrent.CountDownLatch
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadFactory
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import java.util.logging.Level
@ -21,6 +26,17 @@ import net.i2p.data.Destination
@Log
abstract class Connection implements Closeable {
/**
* This exists because the reset() method blocks for a long time
* even though the javadocs say it's non-blocking. When that gets
* fixed on the I2P side, this can be removed.
*/
private static final ExecutorService CLOSER = Executors.newCachedThreadPool( {r ->
def rv = new Thread(r,"connection closer")
rv.setDaemon(true)
rv
} as ThreadFactory)
private static final int SEARCHES = 10
private static final long INTERVAL = 1000
@ -82,7 +98,14 @@ abstract class Connection implements Closeable {
log.info("closing $name")
reader.interrupt()
writer.interrupt()
endpoint.close()
CountDownLatch latch = new CountDownLatch(1)
CLOSER.submit({
endpoint.close()
latch.countDown()
log.info("closed $name")
})
latch.await(3000, TimeUnit.MILLISECONDS)
eventBus.publish(new DisconnectionEvent(destination: endpoint.destination))
}
@ -91,6 +114,7 @@ abstract class Connection implements Closeable {
while(running.get()) {
read()
}
} catch (InterruptedException ok) {
} catch (SocketTimeoutException e) {
} catch (Exception e) {
log.log(Level.WARNING,"unhandled exception in reader",e)
@ -107,6 +131,7 @@ abstract class Connection implements Closeable {
def message = messages.take()
write(message)
}
} catch (InterruptedException ok) {
} catch (Exception e) {
log.log(Level.WARNING, "unhandled exception in writer",e)
} finally {

View File

@ -36,9 +36,8 @@ abstract class ConnectionManager {
timer.schedule({sendPings()} as TimerTask, 1000,1000)
}
void stop() {
void shutdown() {
timer.cancel()
getConnections().each { it.close() }
}
void onTrustEvent(TrustEvent e) {
@ -62,8 +61,6 @@ abstract class ConnectionManager {
abstract void onDisconnectionEvent(DisconnectionEvent e)
abstract void shutdown()
protected void sendPings() {
final long now = System.currentTimeMillis()
getConnections().each {

View File

@ -104,6 +104,7 @@ class UltrapeerConnectionManager extends ConnectionManager {
@Override
void shutdown() {
super.shutdown()
peerConnections.values().stream().parallel().forEach({v -> v.close()})
leafConnections.values().stream().parallel().forEach({v -> v.close()})
peerConnections.clear()

View File

@ -18,11 +18,8 @@ class Shutdown extends AbstractLifecycleHandler {
@Override
void execute() {
log.info("shutting down")
log.info("shutting down from lifecycle")
Core core = application.context.get("core")
if (core != null) {
Thread t = new Thread({ core.shutdown() } as Runnable)
t.start()
}
core?.shutdown()
}
}