Skip to content

Commit 64276d1

Browse files
authored
Introducing NIO server
Introducing NIO server. Added: - Netty server instead of simple IO-based. Changed: - The way of serialization/deserialization of EPMD messages.
1 parent ddf0ef1 commit 64276d1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+866
-1138
lines changed

.codestyle/checkstyle.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ limitations under the License.
191191
</module>
192192
<module name="MethodLength">
193193
<property name="tokens" value="METHOD_DEF"/>
194-
<property name="max" value="30"/>
194+
<property name="max" value="60"/>
195195
<property name="countEmpty" value="false"/>
196196
</module>
197197
<module name="ParameterNumber">

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1111

1212
- Add more unit and integration tests.
1313

14+
## [0.4.0](https://github.com/appulse-projects/epmd-java/releases/tag/0.4.0) - 2018-02-16
15+
16+
Introducing NIO server.
17+
18+
### Added
19+
20+
- Netty server instead of simple IO-based.
21+
22+
### Changed
23+
24+
- The way of serialization/deserialization of EPMD messages.
25+
1426
## [0.3.3](https://github.com/appulse-projects/epmd-java/releases/tag/0.3.3) - 2018-02-09
1527

1628
Minor fix, using unsigned numbers where they are needed

client/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Include the dependency to your project's pom.xml file:
1414
<dependency>
1515
<groupId>io.appulse.epmd.java</groupId>
1616
<artifactId>client</artifactId>
17-
<version>0.3.3</version>
17+
<version>0.4.0</version>
1818
</dependency>
1919
...
2020
</dependencies>
@@ -23,7 +23,7 @@ Include the dependency to your project's pom.xml file:
2323
or Gradle:
2424

2525
```groovy
26-
compile 'io.appulse.epmd.java:client:0.3.3'
26+
compile 'io.appulse.epmd.java:client:0.4.0'
2727
```
2828

2929
### Create client

client/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ limitations under the License.
2525
<parent>
2626
<groupId>io.appulse</groupId>
2727
<artifactId>epmd-java</artifactId>
28-
<version>0.3.3</version>
28+
<version>0.4.0</version>
2929
</parent>
3030

3131
<groupId>io.appulse.epmd.java</groupId>

core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ limitations under the License.
2525
<parent>
2626
<groupId>io.appulse</groupId>
2727
<artifactId>epmd-java</artifactId>
28-
<version>0.3.3</version>
28+
<version>0.4.0</version>
2929
</parent>
3030

3131
<groupId>io.appulse.epmd.java</groupId>

core/src/main/java/io/appulse/epmd/java/core/mapper/deserializer/DataDeserializer.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818

1919
import io.appulse.epmd.java.core.mapper.DataSerializable;
2020
import io.appulse.epmd.java.core.mapper.deserializer.exception.DeserializationException;
21+
import io.appulse.epmd.java.core.mapper.deserializer.exception.InvalidReceivedMessageTagException;
22+
import io.appulse.epmd.java.core.model.Tag;
23+
import io.appulse.epmd.java.core.model.TaggedMessage;
2124
import io.appulse.utils.Bytes;
2225

26+
import lombok.NonNull;
27+
import lombok.val;
28+
2329
/**
2430
*
2531
* @author Artem Labazin
@@ -28,19 +34,30 @@
2834
class DataDeserializer implements Deserializer {
2935

3036
@Override
31-
public <T> T deserialize (Bytes bytes, Class<T> type) throws DeserializationException {
37+
public <T> T deserialize (@NonNull Bytes bytes, @NonNull Class<T> type) throws DeserializationException {
3238
T result;
3339
try {
3440
result = type.newInstance();
3541
} catch (IllegalAccessException | InstantiationException ex) {
3642
throw new DeserializationException(ex);
3743
}
44+
45+
if (result instanceof TaggedMessage) {
46+
val expectedTag = ((TaggedMessage) result).getTag();
47+
val tag = Tag.of(bytes.getByte());
48+
if (!expectedTag.equals(tag)) {
49+
val message = String.format("Expected tag is: %s, but actual tag is: %s",
50+
expectedTag, tag);
51+
throw new InvalidReceivedMessageTagException(message);
52+
}
53+
}
54+
3855
((DataSerializable) result).read(bytes);
3956
return result;
4057
}
4158

4259
@Override
43-
public boolean isApplicable (Class<?> type) {
60+
public boolean isApplicable (@NonNull Class<?> type) {
4461
return DataSerializable.class.isAssignableFrom(type);
4562
}
4663
}

core/src/main/java/io/appulse/epmd/java/core/mapper/deserializer/EnumDeserializer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818

1919
import static java.nio.charset.StandardCharsets.ISO_8859_1;
2020
import static java.util.Arrays.asList;
21+
import static java.util.Collections.synchronizedSet;
2122
import static java.util.Optional.empty;
2223
import static java.util.Optional.ofNullable;
2324

2425
import java.lang.reflect.InvocationTargetException;
2526
import java.lang.reflect.Method;
2627
import java.lang.reflect.Modifier;
27-
import java.util.Collections;
2828
import java.util.HashSet;
2929
import java.util.Optional;
3030
import java.util.Set;
@@ -46,12 +46,12 @@ class EnumDeserializer implements Deserializer {
4646
private static final Set<String> ENUM_UNKNOWN_VALUE;
4747

4848
static {
49-
ENUM_CREATE_METHODS_NAMES = Collections.synchronizedSet(new HashSet<>(asList(
49+
ENUM_CREATE_METHODS_NAMES = synchronizedSet(new HashSet<>(asList(
5050
"of",
5151
"parse",
5252
"from"
5353
)));
54-
ENUM_UNKNOWN_VALUE = Collections.synchronizedSet(new HashSet<>(asList(
54+
ENUM_UNKNOWN_VALUE = synchronizedSet(new HashSet<>(asList(
5555
"UNDEFINED",
5656
"UNKNOWN"
5757
)));

core/src/main/java/io/appulse/epmd/java/core/mapper/deserializer/MessageDeserializer.java

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,15 @@
1616

1717
package io.appulse.epmd.java.core.mapper.deserializer;
1818

19-
import static io.appulse.epmd.java.core.model.Tag.UNDEFINED;
20-
import static io.appulse.utils.BytesUtils.asInteger;
2119
import static java.util.Arrays.asList;
22-
import static java.util.Optional.ofNullable;
2320

2421
import java.util.List;
22+
import java.util.concurrent.CopyOnWriteArrayList;
2523

26-
import io.appulse.epmd.java.core.mapper.Message;
27-
import io.appulse.epmd.java.core.mapper.deserializer.exception.InvalidReceivedMessageLengthException;
28-
import io.appulse.epmd.java.core.mapper.deserializer.exception.InvalidReceivedMessageTagException;
2924
import io.appulse.epmd.java.core.mapper.deserializer.exception.NoApplicableDeserializerException;
30-
import io.appulse.epmd.java.core.mapper.exception.MessageAnnotationMissingException;
31-
import io.appulse.epmd.java.core.model.Tag;
3225
import io.appulse.utils.Bytes;
3326

34-
import lombok.SneakyThrows;
35-
import lombok.val;
27+
import lombok.NonNull;
3628

3729
/**
3830
*
@@ -44,44 +36,22 @@ public final class MessageDeserializer {
4436
private static final List<Deserializer> DESERIALIZERS;
4537

4638
static {
47-
DESERIALIZERS = asList(
39+
DESERIALIZERS = new CopyOnWriteArrayList<>(asList(
40+
new RequestDeserializer(),
4841
new DataDeserializer(),
4942
new EnumDeserializer()
50-
);
43+
));
5144
}
5245

53-
@SneakyThrows
54-
public <T> T deserialize (byte[] bytes, Class<T> type) {
55-
val buffer = ofNullable(bytes)
56-
.map(Bytes::wrap)
57-
.orElseThrow(NullPointerException::new);
58-
59-
val annotation = ofNullable(type)
60-
.map(it -> it.getAnnotation(Message.class))
61-
.orElseThrow(MessageAnnotationMissingException::new);
62-
63-
if (annotation.lengthBytes() > 0) {
64-
val receivedMessageLength = asInteger(buffer.getBytes(annotation.lengthBytes()));
65-
if (receivedMessageLength != buffer.remaining()) {
66-
val message = String.format("Expected length is %d - %d bytes, but actual length is %d bytes.",
67-
annotation.lengthBytes(), receivedMessageLength, buffer.remaining());
68-
throw new InvalidReceivedMessageLengthException(message);
69-
}
70-
}
71-
72-
if (annotation.value() != UNDEFINED) {
73-
val tag = Tag.of(buffer.getByte());
74-
if (annotation.value() != tag) {
75-
val message = String.format("Expected tag is: %s, but actual tag is: %s",
76-
annotation.value(), tag);
77-
throw new InvalidReceivedMessageTagException(message);
78-
}
79-
}
46+
public <T> T deserialize (@NonNull byte[] bytes, @NonNull Class<T> type) {
47+
return deserialize(Bytes.wrap(bytes), type);
48+
}
8049

50+
public <T> T deserialize (@NonNull Bytes bytes, @NonNull Class<T> type) {
8151
return DESERIALIZERS.stream()
8252
.filter(it -> it.isApplicable(type))
8353
.findAny()
8454
.orElseThrow(NoApplicableDeserializerException::new)
85-
.deserialize(buffer, type);
55+
.deserialize(bytes, type);
8656
}
8757
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appulse.epmd.java.core.mapper.deserializer;
18+
19+
import io.appulse.epmd.java.core.mapper.deserializer.exception.DeserializationException;
20+
import io.appulse.epmd.java.core.mapper.deserializer.exception.InvalidReceivedMessageLengthException;
21+
import io.appulse.epmd.java.core.mapper.deserializer.exception.InvalidReceivedMessageTagException;
22+
import io.appulse.epmd.java.core.model.Tag;
23+
import io.appulse.epmd.java.core.model.request.Request;
24+
import io.appulse.utils.Bytes;
25+
26+
import lombok.NonNull;
27+
import lombok.extern.slf4j.Slf4j;
28+
import lombok.val;
29+
30+
/**
31+
*
32+
* @author Artem Labazin
33+
* @since 0.4.0
34+
*/
35+
@Slf4j
36+
class RequestDeserializer implements Deserializer {
37+
38+
@Override
39+
public <T> T deserialize (@NonNull Bytes bytes, @NonNull Class<T> type) throws DeserializationException {
40+
val length = bytes.getShort();
41+
if (length != bytes.remaining()) {
42+
val message = String.format("Expected length is %d - %d bytes, but actual length is %d bytes.",
43+
2, length, bytes.remaining());
44+
log.error(message);
45+
throw new InvalidReceivedMessageLengthException(message);
46+
}
47+
48+
T result;
49+
try {
50+
result = type.newInstance();
51+
} catch (IllegalAccessException | InstantiationException ex) {
52+
log.error("Deserialized type instantiation error", ex);
53+
throw new DeserializationException(ex);
54+
}
55+
56+
if (!(result instanceof Request)) {
57+
val message = String.format("Deserializing type '%s' is not an instance of '%s'",
58+
type.getSimpleName(), Request.class.getSimpleName());
59+
log.error(message);
60+
throw new DeserializationException(message);
61+
}
62+
val request = (Request) result;
63+
64+
val tag = Tag.of(bytes.getByte());
65+
if (tag != request.getTag()) {
66+
val message = String.format("Expected tag is: %s, but actual tag is: %s",
67+
request.getTag(), tag);
68+
log.error(message);
69+
throw new InvalidReceivedMessageTagException(message);
70+
}
71+
72+
request.read(bytes);
73+
return result;
74+
}
75+
76+
@Override
77+
public boolean isApplicable (@NonNull Class<?> type) {
78+
return Request.class.isAssignableFrom(type);
79+
}
80+
}

core/src/main/java/io/appulse/epmd/java/core/mapper/serializer/DataSerializer.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
import io.appulse.epmd.java.core.mapper.DataSerializable;
2020
import io.appulse.epmd.java.core.mapper.serializer.exception.SerializationException;
21+
import io.appulse.epmd.java.core.model.TaggedMessage;
2122
import io.appulse.utils.Bytes;
2223

24+
import lombok.NonNull;
2325
import lombok.val;
2426

2527
/**
@@ -30,14 +32,18 @@
3032
class DataSerializer implements Serializer {
3133

3234
@Override
33-
public byte[] serialize (Object object, Class<?> type) throws SerializationException {
34-
val body = Bytes.allocate();
35-
((DataSerializable) object).write(body);
36-
return body.array();
35+
public byte[] serialize (@NonNull Object object, @NonNull Class<?> type) throws SerializationException {
36+
val serializable = (DataSerializable) object;
37+
val bytes = serializable instanceof TaggedMessage
38+
? Bytes.allocate().put1B(((TaggedMessage) object).getTag().getCode())
39+
: Bytes.allocate();
40+
41+
serializable.write(bytes);
42+
return bytes.array();
3743
}
3844

3945
@Override
40-
public boolean isApplicable (Class<?> type) {
46+
public boolean isApplicable (@NonNull Class<?> type) {
4147
return DataSerializable.class.isAssignableFrom(type);
4248
}
4349
}

0 commit comments

Comments
 (0)