Skip to content

Commit

Permalink
GEODE-7344: DSFID implements BasicSerializable (apache#4364)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bill authored Nov 26, 2019
1 parent 69d830f commit 518f926
Show file tree
Hide file tree
Showing 21 changed files with 595 additions and 226 deletions.
1 change: 0 additions & 1 deletion extensions/geode-modules-tomcat7/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ dependencies {
}
compile('org.apache.tomcat:tomcat-juli:' + DependencyConstraints.get('tomcat7.version'))


testCompile('org.httpunit:httpunit')
testCompile('junit:junit')
testCompile('org.assertj:assertj-core')
Expand Down
2 changes: 1 addition & 1 deletion extensions/geode-modules-tomcat8/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ dependencies {
}
compile('org.apache.tomcat:tomcat-juli:' + DependencyConstraints.get('tomcat8.version'))
compile('javax.servlet:javax.servlet-api')

integrationTestCompile(project(':geode-dunit')) {
exclude module: 'geode-core'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
* This tests the rolling upgrade for locators with different GOSSIPVERSION.
*/
@Category({MembershipTest.class})
public class TcpServerBackwardCompatDUnitTest extends JUnit4DistributedTestCase {
public class TcpServerGossipVersionDUnitTest extends JUnit4DistributedTestCase {

@Override
public final void postSetUp() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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 org.apache.geode.distributed.internal.tcpserver;

import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION;
import static org.apache.geode.distributed.ConfigurationProperties.NAME;
import static org.apache.geode.distributed.ConfigurationProperties.USE_CLUSTER_CONFIGURATION;
import static org.apache.geode.distributed.internal.membership.adapter.SocketCreatorAdapter.asTcpSocketCreator;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

import org.jetbrains.annotations.NotNull;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import org.apache.geode.distributed.Locator;
import org.apache.geode.distributed.internal.DistributionConfigImpl;
import org.apache.geode.distributed.internal.membership.gms.membership.GMSJoinLeave;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.net.SocketCreator;
import org.apache.geode.internal.net.SocketCreatorFactory;
import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.test.dunit.DistributedTestUtils;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.SerializableRunnableIF;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.rules.DistributedRule;
import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
import org.apache.geode.test.version.TestVersion;
import org.apache.geode.test.version.VersionManager;

/**
* In version 1.12 TcpServer changed: the three pairs of message types used to derive from
* DataSerializable, but as of 1.12 they derive from BasicSerializable.
*
* This test verifies that the current version (1.12 or later) is compatible with the latest
* version before 1.12
*/
@RunWith(Parameterized.class)
@Parameterized.UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
public class TcpServerProductVersionDUnitTest implements Serializable {

private static final TestVersion FIRST_NEW_VERSION = TestVersion.valueOf("1.12.0");

@Rule
public DistributedRule distributedRule =
DistributedRule.builder().withVMCount(0).build();

@BeforeClass
public static void beforeClass() {
SocketCreatorFactory.close();
}

@AfterClass
public static void afterClass() {
SocketCreatorFactory.close();
}

private static final TestVersion oldProductVersion = getOldProductVersion();
private static final TestVersion currentProductVersion =
TestVersion.valueOf(VersionManager.CURRENT_VERSION);

@Parameterized.Parameters(name = "{0}")
public static Collection<VersionConfiguration> data() {
return Arrays.asList(VersionConfiguration.values());
}

/*
* We want the newest _available_ version older than FIRST_NEW_VERSION
*/
private static TestVersion getOldProductVersion() {

final Map<Boolean, List<TestVersion>> groups =
VersionManager.getInstance().getVersionsWithoutCurrent().stream()
.map(TestVersion::valueOf)
.collect(Collectors.partitioningBy(v -> v.lessThan(FIRST_NEW_VERSION)));

final List<TestVersion> olderVersions = groups.get(true);

if (olderVersions.size() < 1) {
throw new AssertionError("Time to decommission TcpServerProductVersionDUnitTest "
+ "because there are no supported versions older than " + FIRST_NEW_VERSION);
}

return olderVersions.get(olderVersions.size() - 1);
}

private enum VersionConfiguration {

// OLD_OLD(oldProductVersion, oldProductVersion),
OLD_CURRENT(oldProductVersion, currentProductVersion),
CURRENT_OLD(currentProductVersion, oldProductVersion);
// CURRENT_CURRENT(currentProductVersion, currentProductVersion);

final TestVersion clientProductVersion;
final TestVersion locatorProductVersion;

VersionConfiguration(final TestVersion clientProductVersion,
final TestVersion locatorProductVersion) {
this.clientProductVersion = clientProductVersion;
this.locatorProductVersion = locatorProductVersion;
}

}

private final VersionConfiguration versions;

public TcpServerProductVersionDUnitTest(final VersionConfiguration versions) {
this.versions = versions;
}

@Test
public void testAllMessageTypes() {
System.out.println("BB: controller clientProductVersion is " + versions.clientProductVersion
+ " and FIRST_NEW_VERSION is " + FIRST_NEW_VERSION);
VM clientVM = Host.getHost(0).getVM(versions.clientProductVersion.toString(), 0);
VM locatorVM = Host.getHost(0).getVM(versions.locatorProductVersion.toString(), 1);
int locatorPort = createLocator(locatorVM, true);

clientVM.invoke(() -> System.out.println("BB: client vm started"));

clientVM.invoke("issue version request",
createRequestResponseFunction(locatorPort, VersionRequest.class.getName(),
VersionResponse.class.getName()));
clientVM.invoke("issue info request",
createRequestResponseFunction(locatorPort, InfoRequest.class.getName(),
InfoResponse.class.getName()));
clientVM.invoke("issue shutdown request",
createRequestResponseFunction(locatorPort, ShutdownRequest.class.getName(),
ShutdownResponse.class.getName()));
}

@NotNull
private SerializableRunnableIF createRequestResponseFunction(
final int locatorPort,
final String requestClassName,
final String responseClassName) {

return () -> {

final Class<?> requestClass = Class.forName(requestClassName);
final Object requestMessage = requestClass.newInstance();

final TcpClient tcpClient;
System.out.println("BB: clientVM clientProductVersion is " + versions.clientProductVersion
+ " and FIRST_NEW_VERSION is " + FIRST_NEW_VERSION);
if (versions.clientProductVersion.greaterThanOrEqualTo(FIRST_NEW_VERSION)) {
tcpClient = getTcpClient();
} else {
tcpClient = getLegacyTcpClient();
}

final Object response = tcpClient
.requestToServer(SocketCreator.getLocalHost(), locatorPort, requestMessage, 1000);

final Class<?> responseClass = Class.forName(responseClassName);

assertThat(response).isInstanceOf(responseClass);
};

}

/*
* The TcpClient class changed in version FIRST_NEW_VERSION. That version (and later)
* no longer has the old constructor TcpClient(final Properties), so we have to access
* that constructor via reflection.
*/
private TcpClient getLegacyTcpClient()
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException {

final Constructor<TcpClient> constructor = TcpClient.class.getConstructor(Properties.class);
return constructor.newInstance(getDistributedSystemProperties());
}

@NotNull
private TcpClient getTcpClient() {

SocketCreatorFactory
.setDistributionConfig(new DistributionConfigImpl(getDistributedSystemProperties()));

return new TcpClient(
asTcpSocketCreator(
SocketCreatorFactory
.getSocketCreatorForComponent(SecurableCommunicationChannel.LOCATOR)),
InternalDataSerializer.getDSFIDSerializer().getObjectSerializer(),
InternalDataSerializer.getDSFIDSerializer().getObjectDeserializer());
}

private int createLocator(VM memberVM, boolean usingOldVersion) {
return memberVM.invoke("create locator", () -> {
System.setProperty(GMSJoinLeave.BYPASS_DISCOVERY_PROPERTY, "true");
try {
int port = 0;
// for stress-tests make sure that an older-version locator doesn't try
// to read state persisted by another run's newer-version locator
if (usingOldVersion) {
port = AvailablePortHelper.getRandomAvailableTCPPort();
DistributedTestUtils.deleteLocatorStateFile(port);
}
return Locator.startLocatorAndDS(port, new File(""), getDistributedSystemProperties())
.getPort();
} finally {
System.clearProperty(GMSJoinLeave.BYPASS_DISCOVERY_PROPERTY);
}
});
}

public Properties getDistributedSystemProperties() {
Properties properties = new Properties();
properties.setProperty(ENABLE_CLUSTER_CONFIGURATION, "false");
properties.setProperty(USE_CLUSTER_CONFIGURATION, "false");
properties.setProperty(NAME, "vm" + VM.getCurrentVMNum());
return properties;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.io.IOException;
import java.io.Serializable;


/**
* An interface for objects whose state can be written/read as primitive types and strings ("data").
* That is, instead of serializing itself to an {@link java.io.ObjectOutputStream}, a
Expand Down
6 changes: 3 additions & 3 deletions geode-core/src/main/java/org/apache/geode/DataSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ public static void writeClass(Class<?> c, DataOutput out) throws IOException {
}

if (c == null || c.isPrimitive()) {
InternalDataSerializer.writePrimitiveClass(c, out);
StaticSerialization.writePrimitiveClass(c, out);
} else {
// non-primitive classes have a second CLASS byte
// if readObject/writeObject is called:
Expand Down Expand Up @@ -263,7 +263,7 @@ public static Class<?> readClass(DataInput in) throws IOException, ClassNotFound
String className = readString(in);
return InternalDataSerializer.getCachedClass(className);
} else {
return InternalDataSerializer.decodePrimitiveClass(typeCode);
return StaticSerialization.decodePrimitiveClass(typeCode);
}
}

Expand Down Expand Up @@ -1741,7 +1741,7 @@ public static Object[] readObjectArray(DataInput in) throws IOException, ClassNo
if (typeCode == DSCODE.CLASS.toByte()) {
c = InternalDataSerializer.getCachedClass(typeString);
} else {
c = InternalDataSerializer.decodePrimitiveClass(typeCode);
c = StaticSerialization.decodePrimitiveClass(typeCode);
}
}
Object o = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,14 @@

package org.apache.geode.distributed.internal.tcpserver;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.geode.DataSerializable;
import org.apache.geode.internal.serialization.BasicSerializable;

/**
* A request to the TCP server to provide information about the server
*
* @since GemFire 5.7
*
*/
public class InfoRequest implements DataSerializable {
private static final long serialVersionUID = -9129777520477738699L;

@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {}

@Override
public void toData(DataOutput out) throws IOException {}
public class InfoRequest implements BasicSerializable {
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@
import java.io.DataOutput;
import java.io.IOException;

import org.apache.geode.DataSerializable;
import org.apache.geode.internal.serialization.BasicSerializable;
import org.apache.geode.internal.serialization.DeserializationContext;
import org.apache.geode.internal.serialization.SerializationContext;
import org.apache.geode.internal.serialization.StaticSerialization;

/**
* A response from the TCP server with information about the server
*
* @since GemFire 5.7
*/
public class InfoResponse implements DataSerializable {
private static final long serialVersionUID = 6249492407448855032L;
public class InfoResponse implements BasicSerializable {
private String[] info;

public InfoResponse(String[] info) {
Expand All @@ -43,12 +44,13 @@ public String[] getInfo() {
}

@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
info = StaticSerialization.readStringArray(in);
public void toData(final DataOutput out, final SerializationContext context) throws IOException {
StaticSerialization.writeStringArray(info, out);
}

@Override
public void toData(DataOutput out) throws IOException {
StaticSerialization.writeStringArray(info, out);
public void fromData(final DataInput in, final DeserializationContext context)
throws IOException, ClassNotFoundException {
info = StaticSerialization.readStringArray(in);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,13 @@

package org.apache.geode.distributed.internal.tcpserver;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.geode.DataSerializable;
import org.apache.geode.internal.serialization.BasicSerializable;

/**
* A request to the TCP server to shutdown
*
* @since GemFire 5.7
*/
public class ShutdownRequest implements DataSerializable {
private static final long serialVersionUID = 7920535743546544136L;

@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {}

@Override
public void toData(DataOutput out) throws IOException {}
public class ShutdownRequest implements BasicSerializable {
}
Loading

0 comments on commit 518f926

Please sign in to comment.