RMI cleanup/polish
This commit is contained in:
parent
f8d71b96dd
commit
6c97567d04
|
@ -38,11 +38,11 @@ import com.esotericsoftware.kryo.io.Input;
|
|||
import com.esotericsoftware.kryo.io.Output;
|
||||
import com.esotericsoftware.kryo.serializers.CollectionSerializer;
|
||||
import com.esotericsoftware.kryo.serializers.FieldSerializer;
|
||||
import com.esotericsoftware.kryo.util.IdentityMap;
|
||||
import com.esotericsoftware.kryo.util.IntMap;
|
||||
import com.esotericsoftware.kryo.util.MapReferenceResolver;
|
||||
|
||||
import dorkbox.network.connection.ping.PingMessage;
|
||||
import dorkbox.network.rmi.ClassDefinitions;
|
||||
import dorkbox.network.rmi.InvocationHandlerSerializer;
|
||||
import dorkbox.network.rmi.InvocationResultSerializer;
|
||||
import dorkbox.network.rmi.InvokeMethod;
|
||||
|
@ -178,7 +178,8 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
|
|||
// used to track which interface -> implementation, for use by RMI
|
||||
private final IntMap<Class<?>> rmiIdToImpl = new IntMap<Class<?>>();
|
||||
private final IntMap<Class<?>> rmiIdToIface = new IntMap<Class<?>>();
|
||||
private final ClassDefinitions classDefinitions = new ClassDefinitions();
|
||||
private final IdentityMap<Class<?>, Class<?>> rmiIfacetoImpl = new IdentityMap<Class<?>, Class<?>>();
|
||||
private final IdentityMap<Class<?>, Class<?>> rmiImplToIface = new IdentityMap<Class<?>, Class<?>>();
|
||||
|
||||
/**
|
||||
* By default, the serialization manager will compress+encrypt data to connections with remote IPs, and only compress on the loopback IP
|
||||
|
@ -272,6 +273,7 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
|
|||
int id = kryo.register(remoteImplClass.implClass, remoteObjectSerializer).getId();
|
||||
|
||||
// sets up the RMI, so when we receive the iface class from the client, we know what impl to use
|
||||
// if this is over-written, we don't care.
|
||||
rmiIdToImpl.put(id, remoteImplClass.implClass);
|
||||
rmiIdToIface.put(id, remoteImplClass.ifaceClass);
|
||||
}
|
||||
|
@ -403,7 +405,15 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
|
|||
classesToRegister.add(new RemoteImplClass(ifaceClass, implClass));
|
||||
|
||||
// this MUST BE UNIQUE otherwise unexpected things can happen.
|
||||
classDefinitions.set(ifaceClass, implClass);
|
||||
Class<?> a = this.rmiIfacetoImpl.put(ifaceClass, implClass);
|
||||
Class<?> b = this.rmiImplToIface.put(implClass, ifaceClass);
|
||||
|
||||
// this MUST BE UNIQUE otherwise unexpected things can happen.
|
||||
if (a != null || b != null) {
|
||||
throw new IllegalArgumentException("Unable to override interface (" + ifaceClass + ") and implementation (" + implClass + ") " +
|
||||
"because they have already been overridden by something else. It is critical that they are" +
|
||||
" both unique per JVM");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -439,7 +449,9 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
|
|||
public synchronized
|
||||
void finishInit() {
|
||||
initialized = true;
|
||||
// initialize the kryo pool with at least 1 kryo instance. This ALSO makes sure that all of our class registration is done correctly
|
||||
|
||||
// initialize the kryo pool with at least 1 kryo instance. This ALSO makes sure that all of our class registration is done
|
||||
// correctly and (if not) we are are notified on the initial thread (instead of on the network udpate thread)
|
||||
kryoPool.put(takeKryo());
|
||||
}
|
||||
|
||||
|
@ -461,6 +473,19 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
|
|||
return rmiIdToIface.get(objectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RMI implementation based on the specified ID (which is the ID for the registered interface)
|
||||
*
|
||||
* @param objectId ID of the registered interface, which will map to the corresponding implementation.
|
||||
*
|
||||
* @return the implementation for the interface, or null
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
Class<?> getRmiImpl(int objectId) {
|
||||
return rmiIdToImpl.get(objectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RMI implementation based on the specified interface
|
||||
*
|
||||
|
@ -469,7 +494,7 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
|
|||
@Override
|
||||
public
|
||||
Class<?> getRmiImpl(Class<?> iface) {
|
||||
return classDefinitions.get(iface);
|
||||
return rmiIfacetoImpl.get(iface);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -480,19 +505,7 @@ class CryptoSerializationManager implements dorkbox.network.util.CryptoSerializa
|
|||
@Override
|
||||
public
|
||||
Class<?> getRmiIface(Class<?> implementation) {
|
||||
return classDefinitions.getReverse(implementation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RMI implementation based on the specified ID (which is the ID for the registered interface)
|
||||
*
|
||||
* @param objectId ID of the registered interface, which will map to the corresponding implementation.
|
||||
* @return the implementation for the interface, or null
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
Class<?> getRmiImpl(int objectId) {
|
||||
return rmiIdToImpl.get(objectId);
|
||||
return rmiImplToIface.get(implementation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.network.rmi;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
import com.esotericsoftware.kryo.util.IdentityMap;
|
||||
|
||||
/**
|
||||
* Uses the "single writer principle" for fast access
|
||||
*/
|
||||
public
|
||||
class ClassDefinitions {
|
||||
// not concurrent because they are setup during system initialization
|
||||
private volatile IdentityMap<Class<?>, Class<?>> overriddenMethods = new IdentityMap<Class<?>, Class<?>>();
|
||||
private volatile IdentityMap<Class<?>, Class<?>> overriddenReverseMethods = new IdentityMap<Class<?>, Class<?>>();
|
||||
|
||||
private static final AtomicReferenceFieldUpdater<ClassDefinitions, IdentityMap> overriddenMethodsREF =
|
||||
AtomicReferenceFieldUpdater.newUpdater(ClassDefinitions.class,
|
||||
IdentityMap.class,
|
||||
"overriddenMethods");
|
||||
|
||||
private static final AtomicReferenceFieldUpdater<ClassDefinitions, IdentityMap> overriddenReverseMethodsREF =
|
||||
AtomicReferenceFieldUpdater.newUpdater(ClassDefinitions.class,
|
||||
IdentityMap.class,
|
||||
"overriddenReverseMethods");
|
||||
|
||||
public
|
||||
ClassDefinitions() {
|
||||
}
|
||||
|
||||
/**
|
||||
* access a snapshot of the overridden methods (single-writer-principle)
|
||||
*/
|
||||
public
|
||||
Class<?> get(final Class<?> type) {
|
||||
//noinspection unchecked
|
||||
final IdentityMap<Class<?>, Class<?>> identityMap = overriddenMethodsREF.get(this);
|
||||
return identityMap.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* access a snapshot of the overridden methods (single-writer-principle)
|
||||
*/
|
||||
public
|
||||
Class<?> getReverse(final Class<?> type) {
|
||||
//noinspection unchecked
|
||||
final IdentityMap<Class<?>, Class<?>> identityMap = overriddenReverseMethodsREF.get(this);
|
||||
return identityMap.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the iface/impl have previously been overridden
|
||||
*/
|
||||
// synchronized to make sure only one writer at a time
|
||||
public synchronized
|
||||
void set(final Class<?> ifaceClass, final Class<?> implClass) {
|
||||
Class<?> a = this.overriddenMethods.put(ifaceClass, implClass);
|
||||
Class<?> b = this.overriddenReverseMethods.put(implClass, ifaceClass);
|
||||
|
||||
// this MUST BE UNIQUE otherwise unexpected things can happen.
|
||||
if (a != null || b != null) {
|
||||
throw new IllegalArgumentException("Unable to override interface (" + ifaceClass + ") and implementation (" + implClass + ") " +
|
||||
"because they have already been overridden by something else. It is critical that they are" +
|
||||
" both unique per JVM");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,12 +104,9 @@ class RmiProxyHandler implements InvocationHandler {
|
|||
byte responseID = invokeMethodResult.responseID;
|
||||
|
||||
if (invokeMethodResult.objectID != objectID) {
|
||||
// System.err.println("FAILED: " + responseID);
|
||||
// logger.trace("{} FAILED to received data: {} with id ({})", connection, invokeMethodResult.result, invokeMethodResult.responseID);
|
||||
return;
|
||||
}
|
||||
|
||||
// logger.trace("{} received data: {} with id ({})", connection, invokeMethodResult.result, invokeMethodResult.responseID);
|
||||
synchronized (this) {
|
||||
if (RmiProxyHandler.this.pendingResponses[responseID]) {
|
||||
RmiProxyHandler.this.responseTable[responseID] = invokeMethodResult;
|
||||
|
|
Loading…
Reference in New Issue
Block a user