Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds cluster version and node-cluster version validation. #9243

Merged
merged 1 commit into from Nov 21, 2016

Conversation

Projects
None yet
5 participants
@vbekiaris
Copy link
Contributor

commented Nov 11, 2016

Adds the notion of cluster version to Cluster and codebase version to Node. Main changes:

  • Added cluster version & node version
  • During node join, node version is validated for compatibility with current cluster version

Requires an EE counterpart. (hazelcast/hazelcast-enterprise#1123)

@vbekiaris vbekiaris added this to the 3.8 milestone Nov 11, 2016

@vbekiaris vbekiaris self-assigned this Nov 11, 2016

@@ -169,6 +170,16 @@
void changeClusterState(ClusterState newState, TransactionOptions transactionOptions);

/**
*
* @return the version at which this cluster operates.

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Can you add a line regarding null? Can it ever be null?

*/
Version getClusterVersion();

void changeClusterVersion(Version version);

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Javadoc needed. And what about calling this 'setCusterVersion' ? What is the added value of calling this 'change'?

@@ -258,4 +260,12 @@
*/
void removeAttribute(String key);

/**
* Returns the Hazelcast version of this member; this may or may not be different from the version reported by

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Under which conditions can this be different?

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

It's the codebase version (not the cluster version).
@vbekiaris Maybe we can formulate it like this Returns the Hazelcast codebase version of this member

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

Aha, now I see it's not a codebase version, but a member's version. but in this case it should be always equal to clusterVersion?

@@ -57,13 +58,14 @@ private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Are we sure this exception isn't picked up by the client? If so, there could be a compatibility issue.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 11, 2016

Author Contributor

Client-side exceptions are instantiated on the client-side by ClientExceptionFactory that only delivers the exception type, message and stack trace elements, not using java serialization.

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Ok. good to know.

@@ -16,15 +16,16 @@

package com.hazelcast.instance;

import com.hazelcast.nio.serialization.impl.BinaryInterface;
import com.hazelcast.cluster.MemberAttributeOperationType;
import com.hazelcast.core.Member;
import com.hazelcast.logging.ILogger;
import com.hazelcast.nio.Address;

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

This class is used as a parent class on the client side. Are we sure this isn't going to cause wire incompatibilities?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 11, 2016

Author Contributor

Member class in client protocol is serialized/deserialized using the dedicated com.hazelcast.client.impl.protocol.codec.MemberCodec, the serialized form implemented in AbstractMember is only relevant for member-to-member communication.

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Ok. THanks

listener.onClusterVersionChange(newVersion);
}
// also trigger cluster version change on explicitly registered listeners
if (!clusterVersionListeners.isEmpty()) {

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

I would remove the if. This logic isn't going to be called frequently.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 11, 2016

Author Contributor

Done

}

@Override
public boolean isNodeVersionCompatibleWith(Version clusterVersion) {

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Should this not be a function implemented on the version itself?

E.g. if(node.getVersion().isCompatible(clusterVersion))...

This way you keep the NodeExtension a bit cleaner. The code becomes a bit more cohesive since the version related functions are bundled in the version.

Or do you need this function here so you can override it in the enterprise NodeExtension?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 11, 2016

Author Contributor

Yes, both validations introduced in NodeExtension are overridden in EE side.

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Ok. then it makes sense to do it like this.

* Listeners interested on acting upon cluster version update should implement this interface.
* Services registered with the Hazelcast {@link com.hazelcast.spi.impl.servicemanager.ServiceManager} which implement this
* interface do not have have to register themselves, as their {@link #onClusterVersionChange(Version)} method will be invoked
* automatically.

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Probably we should add a line regarding async vs async listener notification. If it is sync, probably add a warning; don't do something stupid on the thread because you could stall the system.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 11, 2016

Author Contributor

Added documentation in onClusterVersionChanged method javadoc.

int thisVersion = (major << 24 & 0xff0000) | ((minor << 16) & 0xff00) | (patch & 0xff);
int thatVersion = (otherVersion.major << 24 & 0xff0000) | (otherVersion.minor << 16 & 0xff00)
| (otherVersion.patch & 0xff);
return (thisVersion > thatVersion) ? 1 : (thisVersion == thatVersion ? 0 : -1);

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Nested ternary operations are a pain to read. Can you convert the outer one to an if else?

@@ -41,15 +42,15 @@ public void testConstructor() {

@Test
public void testConstructor_withAddress() {
MemberImpl member = new MemberImpl(address);
MemberImpl member = new MemberImpl(address, Version.of("3.8.0"));

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

Is this not going to cause problems as soon as we move to the development of 3.9? So do we really want to have a hardcoded 3.8.0 in the system?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 11, 2016

Author Contributor

In the particular test we need a fixed version in the constructed member objects to validate. In any case I have reverted to using a Version object for the current codebase version in other tests which do not need a fixed version to validate, to avoid unpleasant surprises in the future.

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch from 7c23209 to ac088c8 Nov 11, 2016

return MAJOR_MINOR_VERSION_COMPARATOR.compare(node.getVersion(), clusterVersion) == 0;
}

@Override
public boolean registerListener(Object listener) {

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 11, 2016

Member

Just a reminder for EE counterpart;
EnterpriseNodeExtension.registerListener() is not calling super.registerListener() right now.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 11, 2016

Author Contributor

Thanks, it's in the EE-side PR.

private void doSetClusterState(ClusterState newState, boolean isTransient) {
this.state = newState;
stateLockRef.set(ClusterStateLock.NOT_LOCKED);
changeNodeState(newState);
node.getNodeExtension().onClusterStateChange(newState, isTransient);
}

private void doSetClusterVersion(Version newVersion) {

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 11, 2016

Member

I think we should persist cluster version in Hot Restart. Think that cluster is shutdown when there are mixed version of members in cluster... During restart, emulated cluster version should be restored back.

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

We should also capture it in the diagnostics so we can see when a cluster change has happened.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

@pveentjer I added a cluster version change listener in SystemLogPlugin. Test to verify output will be on the EE-side PR.

* as well as some backports of newer Java features / data structures to
* support older Java versions in a clean and nice way.
*
* This is an internal package; so we don't provide backward compatibility on these classes.

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 11, 2016

Member

not an internal package?

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch from ac088c8 to f5c6990 Nov 11, 2016

void changeClusterVersion(Version version);

/**
* Changes the cluster version transactionally, with the transaction options provided. Internally this method uses the same

This comment has been minimized.

Copy link
@pveentjer

pveentjer Nov 11, 2016

Member

I'm failing to understand something here. Should these methods for changing the cluster version be part of the public api? Meaning that the user can change it himself?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

Once all nodes of the cluster have been upgraded, cluster version needs to be also upgraded via cluster.sh or management center. A cluster version upgrade is executed transactionally on the cluster and in the process each node validates it's compatible with the requested cluster version change. I think it's a valid entry point for Cluster API, wdyt?

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 15, 2016

Member

Do you allow this method to be called with an arbitrary version number? Or is it going to be only a trigger to upgrade cluster version?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

The invoker sets the requested version number, so it is possible one could invoke it with any version number, valid or not. Without the Version argument the method's utility would be limited, as it would only allow for one-way change (upgrade) to the "next" version, where "next"'s meaning would be essentially hard-coded in the method's implementation.

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 15, 2016

Member

I see.. but method's utility is already limited, right? At least for now... It cannot set cluster version to any number, it's only for upgrade (and downgrade?).
What if we don't expose it in public api but only via REST, shell script and management center?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

👍 I am moving it to internal ClusterService API

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch 7 times, most recently from 9d1b87c to 0e8e885 Nov 14, 2016

if (overridingVersion != null) {
version = overridingVersion;
}

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

What will we do with this version overriding? Maybe let's keep it without documenting it and maybe logging a warning message if somebody uses it?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

👍 for logging a message if used and keeping undocumented; having means to override the version is very useful for tests.

node.getClusterService().getClusterVersion()) != 0) {
throw new VersionMismatchException("Joining node's version " + joinRequest.getVersion() + " is not compatible with "
+ node.getVersion());
}

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

This constraint is something that we're introducing right now. Earlier, if by any chance two minor releases were compatible, the users might have tried to do a rolling-upgrade and it might have worked.
Do we want to have this constraint considering that the versioned serialization won't work in OS anyway?
CC: @jerrinot

systemLogger.info("Cluster version changed to " + newVersion);
NodeEngineImpl nodeEngine = node.getNodeEngine();
ServiceManager serviceManager = nodeEngine.getServiceManager();
List<ClusterVersionListener> listeners = serviceManager.getServices(ClusterVersionListener.class);

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

Just a minor one - you could inline nodeEngine since it's used once only.

* The cluster version indicates the operating version of the cluster. It is separate from each node's codebase version,
* as it may be acceptable for a node to operate at a different compatibility version than its codebase version. This method
* may return {@code null} if invoked after the ClusterService is constructed and before the node forms a cluster, either
* by joining existing members or becoming master of its standalone cluster if it is the first node on the cluster.

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

So now we wait with setting the clusterVersion to the node's version until the node's gets elected as a master of the one-node cluster? Where does this happen?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

This happens in Node.setAsMaster(), invoked during Node.join().

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 16, 2016

Contributor

Hmm, but now I'm thinking that if it returns a null the operation serialized to join a cluster do not send any version. I think it was better to have it set to Node's version first, since there has to be a version all the time.
I mean for versioned serialization purposes.
Wdyt?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 16, 2016

Author Contributor

Since the serialization service registers its own cluster version listener, it will never receive a null cluster version; when Cluster.getClusterVersion()==null it will initialize the listener with the node's codebase version.

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 17, 2016

Contributor

OK, as discussed there will be a property to set the version that should be used before the proper cluster version is set. It's for the sake of backward compatibility, to properly serialize the join messages.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 17, 2016

Author Contributor

Done

public void validateJoinRequest(JoinRequest joinRequest) {
// check joining member's major.minor version is same as current cluster version's major.minor numbers
if (node.getClusterService().getClusterVersion() != null
&& MAJOR_MINOR_VERSION_COMPARATOR.compare(joinRequest.getVersion(),

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

The cluster version should not be null? I mean the node should be a master already, otherwise it's risky business.
Why would someone join not-master node?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

Null check was redundant, removed it

@@ -124,7 +125,7 @@ private void dispatchEntryEventData(EntryEventData entryEventData, ListenerAdapt
private Member getMember(EventData eventData) {
Member member = nodeEngine.getClusterService().getMember(eventData.getCaller());
if (member == null) {
member = new MemberImpl(eventData.getCaller(), false);
member = new MemberImpl(eventData.getCaller(), Version.UNKNOWN, false);
}

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

What is this for? and why do we publish unknown?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

good catch, the member that publishes the event has version node.version.

@Override
@SuppressWarnings("checkstyle:booleanexpressioncomplexity")
public int compareTo(Version otherVersion) {
int thisVersion = (major << 16 & 0xff0000) | ((minor << 8) & 0xff00) | (patch & 0xff);

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

Can you add some javadoc here ;) ? It's tough to read those binary operators.


/**
* Version comparator that disregards patch version.
*/

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

Maybe it's good to add : and compares the major and minor versions only

@SuppressWarnings("checkstyle:magicnumber")
public final class Version implements IdentifiedDataSerializable, Comparable<Version>, Serializable {


This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

Jaromir had a couple of comments to this class in my PR (but I see it's a bit different now)
Here's the link: #9229

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 16, 2016

Author Contributor

@jerrinot Version is IDS & has public constructors in this PR.

With regards to semantics of Version.UNKNOWN, in the context of this PR it is used to populate the version field in client-side MemberImpl as client is not aware of the version of each member.

In Version class patch field is considered to be always available: if the Version instance is initialized via parsing a String which lacks the patch component, it is initialized to 0. Version.equals requires all 3 components to be equal. A separate major.minor-only comparator is also provided and used where appropriate (e.g. when testing node codebase version vs cluster version compatibility in this PR, we require major.minor equality, allowing for patch-level compatibility only).

assertTrue(MAJOR_MINOR_VERSION_COMPARATOR.compare(VERSION_3_8_1, VERSION_3_9) < 0);
}

}

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

Did you get rid of the test verifying the race between joiner and cluster-version change?

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 15, 2016

Author Contributor

good one, I will restore it

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 15, 2016

Contributor

Cool, probably it should be in EE though.

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch 2 times, most recently from 0f1e300 to 2e5c9db Nov 15, 2016

if (MAJOR_MINOR_VERSION_COMPARATOR.compare(joinMessage.getVersion(), node.getClusterService().getClusterVersion()) != 0) {
throw new VersionMismatchException("Joining node's version " + joinMessage.getVersion() + " is not compatible with "
+ node.getVersion());
}

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 16, 2016

Contributor

This constraint is something that we're introducing right now. Earlier, if by any chance two minor releases were compatible, the users might have tried to do a rolling-upgrade and it might have worked.
Do we want to have this constraint considering that the versioned serialization won't work in OS anyway?
CC: @jerrinot
(posting again so that it's not seen in outdated view)

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 17, 2016

Contributor

As discussed, it's fine to leave this check here.

@@ -258,4 +260,15 @@
*/
void removeAttribute(String key);

/**
* Returns the Hazelcast codebase version of this member; this may or may not be different from the version reported by
* {@link ClusterService#getClusterVersion()}, for example when a node with a different codebase version is added to an

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 16, 2016

Contributor

Ah, now I get it. So the Member.version is the version of Member X on stored on another member.

assertTrue(nodeExtension.registerListener(listener));
assertOpenEventually(latch);
}

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 16, 2016

Contributor

Could we have a test to guard the the listener will get node's codebase version if cluster.getVersion is null?
Otherwise the versioned serialization will be screwed.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 16, 2016

Author Contributor

Added in DefaultNodeExtensionTest

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 17, 2016

Contributor

Great. thx

*/
public static final transient Comparator<Version> MAJOR_MINOR_VERSION_COMPARATOR = new MajorMinorVersionComparator();

// private static final int UNKNOWN_VERSION_COMPONENT = 0;

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 16, 2016

Contributor

can be removed

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 16, 2016

Author Contributor

Done

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch 3 times, most recently from ed06465 to a536236 Nov 16, 2016

@devOpsHazelcast

This comment has been minimized.

Copy link
Contributor

commented Nov 17, 2016

Test PASSed.

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch from a536236 to e2ad8f6 Nov 17, 2016

* of a cluster running on different Hazelcast codebase versions. The default is to use the node's codebase version. You may
* need to override it for your node to join a cluster running on a previous cluster version.
*/
public static final HazelcastProperty INIT_CLUSTER_VERSION

This comment has been minimized.

Copy link
@tombujok

tombujok Nov 17, 2016

Contributor

Looks good. Nice description.

@vbekiaris vbekiaris changed the title [WIP] Adds cluster version and node-cluster version validation. Adds cluster version and node-cluster version validation. Nov 17, 2016

@devOpsHazelcast

This comment has been minimized.

Copy link
Contributor

commented Nov 17, 2016

Test PASSed.

* Returns the Hazelcast codebase version of this member; this may or may not be different from the version reported by
* {@link ClusterService#getClusterVersion()}, for example when a node with a different codebase version is added to an
* existing cluster. See the documentation for {@link ClusterService#getClusterVersion()} for a more thorough discussion
* of {@code Cluster} and {@code Member} / {@code Node} version.

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 18, 2016

Member

Can you change {@link ClusterService#getClusterVersion()} to {@link Cluster#getClusterVersion()}? This is a public class and I don't think it's desired to refer/import an internal class here.

@@ -695,6 +704,7 @@ public void setAsMaster() {
setJoined();

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 18, 2016

Member

I think setJoined() should be the last statement, once node is observed as joined, cluster version (and other props) should be visible.

This comment has been minimized.

Copy link
@vbekiaris

vbekiaris Nov 18, 2016

Author Contributor

well spotted; actually changeClusterVersion kicks-off the cluster state change to apply cluster version on each member of the cluster. I think this is not necessary at this point, as it is enough to just set the local cluster version property, if not already set; subsequent FinalizeJoinOperations will apply the cluster version to each member joining the cluster.

@@ -124,7 +124,7 @@ private void dispatchEntryEventData(EntryEventData entryEventData, ListenerAdapt
private Member getMember(EventData eventData) {
Member member = nodeEngine.getClusterService().getMember(eventData.getCaller());
if (member == null) {
member = new MemberImpl(eventData.getCaller(), false);
member = new MemberImpl(eventData.getCaller(), nodeEngine.getNode().getVersion(), false);

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 18, 2016

Member

Shouldn't node's codebase version be available on NodeEngine interface? NodeEngine.getVersion()? So, no need to cast impl...

@Rule
public ExpectedException expectedException = ExpectedException.none();

private TestHazelcastInstanceFactory factory = new TestHazelcastInstanceFactory(10);

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 18, 2016

Member

minor note:
When private TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(10) is used, factory will be tear down automatically by HazelcastTestSupport.shutdownNodeFactory().

/**
* Test DefaultNodeExtension behavior
*/
public class DefaultNodeExtensionTest extends HazelcastTestSupport {

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 18, 2016

Member

No @Category is provided.

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch from c92cba1 to 82558ba Nov 18, 2016

@vbekiaris

This comment has been minimized.

Copy link
Contributor Author

commented Nov 18, 2016

@mdogan rebased & amended according to your comments.

@devOpsHazelcast

This comment has been minimized.

Copy link
Contributor

commented Nov 18, 2016

Test PASSed.

1 similar comment
@devOpsHazelcast

This comment has been minimized.

Copy link
Contributor

commented Nov 18, 2016

Test PASSed.

@mdogan

mdogan approved these changes Nov 21, 2016

setJoined();
getClusterService().getClusterClock().setClusterStartTime(Clock.currentTimeMillis());
getClusterService().setClusterId(UuidUtil.createClusterUuid());
// getClusterService().changeClusterVersion(version);

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 21, 2016

Member

minor: left over, commented out.

@@ -160,7 +160,7 @@ public void fireMapClearedEvent(int deletedEntrySize, String name) {
private Member getMember(EventData eventData) {
Member member = replicatedMapService.getNodeEngine().getClusterService().getMember(eventData.getCaller());
if (member == null) {
member = new MemberImpl(eventData.getCaller(), false);
member = new MemberImpl(eventData.getCaller(), nodeEngine.getNode().getVersion(), false);

This comment has been minimized.

Copy link
@mdogan

mdogan Nov 21, 2016

Member

minor: nodeEngine.getVersion()

@vbekiaris vbekiaris force-pushed the vbekiaris:rolling/3.8/cluster-version branch from 82558ba to 018222c Nov 21, 2016

@devOpsHazelcast

This comment has been minimized.

Copy link
Contributor

commented Nov 21, 2016

Test PASSed.

@vbekiaris vbekiaris merged commit 55a6560 into hazelcast:master Nov 21, 2016

1 check passed

default Build finished.
Details
@vbekiaris

This comment has been minimized.

Copy link
Contributor Author

commented Nov 21, 2016

Thanks @pveentjer , @mdogan , @tombujok , @jerrinot for the reviews & comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.