Potential fix for bootstrap registration iteration errors

This commit is contained in:
nathan 2018-01-11 14:56:52 +01:00
parent 5b890a623a
commit 542092a7b3

View File

@ -16,9 +16,9 @@
package dorkbox.network.connection; package dorkbox.network.connection;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -40,8 +40,10 @@ class EndPointClient<C extends Connection> extends EndPointBase<C> implements Ru
protected final Object registrationLock = new Object(); protected final Object registrationLock = new Object();
protected final AtomicInteger connectingBootstrap = new AtomicInteger(0); protected final Object bootstrapLock = new Object();
protected List<BootstrapWrapper> bootstraps = new LinkedList<BootstrapWrapper>(); protected List<BootstrapWrapper> bootstraps = new LinkedList<BootstrapWrapper>();
protected Iterator<BootstrapWrapper> bootstrapIterator;
protected volatile int connectionTimeout = 5000; // default protected volatile int connectionTimeout = 5000; // default
protected volatile boolean registrationComplete = false; protected volatile boolean registrationComplete = false;
private volatile boolean rmiInitializationComplete = false; private volatile boolean rmiInitializationComplete = false;
@ -56,40 +58,36 @@ class EndPointClient<C extends Connection> extends EndPointBase<C> implements Ru
protected protected
void registerNextProtocol() { void registerNextProtocol() {
this.registrationComplete = false; // always reset. // always reset everything.
this.registrationComplete = false;
bootstrapIterator = bootstraps.iterator();
startProtocolRegistration();
}
private
void startProtocolRegistration() {
new Thread(this, "Bootstrap registration").start(); new Thread(this, "Bootstrap registration").start();
} }
// not protected by synchronized // protected by bootstrapLock
private
BootstrapWrapper getNextBootstrap() {
int bootstrapToRegister = this.connectingBootstrap.getAndIncrement();
if (bootstrapToRegister == this.bootstraps.size()) {
return null;
}
return this.bootstraps.get(bootstrapToRegister);
}
// not protected by synchronized
private private
boolean isRegistrationComplete() { boolean isRegistrationComplete() {
return this.connectingBootstrap.get() == this.bootstraps.size(); return !bootstrapIterator.hasNext();
} }
@SuppressWarnings("AutoBoxing") @SuppressWarnings("AutoBoxing")
@Override @Override
public public
void run() { void run() {
synchronized (this.connectingBootstrap) { synchronized (this.bootstrapLock) {
BootstrapWrapper bootstrapWrapper = getNextBootstrap(); if (isRegistrationComplete()) {
if (bootstrapWrapper == null) {
return; return;
} }
BootstrapWrapper bootstrapWrapper = bootstrapIterator.next();
ChannelFuture future; ChannelFuture future;
if (this.connectionTimeout != 0) { if (this.connectionTimeout != 0) {
@ -135,13 +133,17 @@ class EndPointClient<C extends Connection> extends EndPointBase<C> implements Ru
@Override @Override
protected protected
boolean registerNextProtocol0() { boolean registerNextProtocol0() {
synchronized (this.connectingBootstrap) { synchronized (this.bootstrapLock) {
this.registrationComplete = isRegistrationComplete(); this.registrationComplete = isRegistrationComplete();
if (!this.registrationComplete) { if (!this.registrationComplete) {
registerNextProtocol(); startProtocolRegistration();
} }
// we're done with registration, so no need to keep this around
bootstrapIterator = null;
} }
Logger logger2 = this.logger; Logger logger2 = this.logger;
if (logger2.isTraceEnabled()) { if (logger2.isTraceEnabled()) {
logger2.trace("Registered protocol from server."); logger2.trace("Registered protocol from server.");