diff --git a/.nuget/packages.config b/.nuget/packages.config
index da7ace8042..a6e460ed07 100644
--- a/.nuget/packages.config
+++ b/.nuget/packages.config
@@ -1,6 +1,6 @@
-
+
-
+
\ No newline at end of file
diff --git a/Hazelcast.Net/Hazelcast.Client.Proxy/ClientMapProxy.cs b/Hazelcast.Net/Hazelcast.Client.Proxy/ClientMapProxy.cs
index ecb2dc4eaa..98efae7573 100644
--- a/Hazelcast.Net/Hazelcast.Client.Proxy/ClientMapProxy.cs
+++ b/Hazelcast.Net/Hazelcast.Client.Proxy/ClientMapProxy.cs
@@ -702,7 +702,7 @@ private ArrayList GetPartitionKeyData(ICollection keys)
var partitionService = GetContext().GetPartitionService();
var partitionCount = partitionService.GetPartitionCount();
var initialCapacity = 2 * (keys.Count / partitionCount);
- var partitionToKeyData = new ArrayList(partitionCount);
+ var partitionToKeyData = ArrayList.Synchronized(new ArrayList(partitionCount));
for (var i = 0; i < partitionCount; i++)
{
partitionToKeyData.Add(ArrayList.Synchronized(new ArrayList(initialCapacity)));
@@ -765,9 +765,9 @@ public void PutAll(IDictionary m)
var partitions = new ArrayList(partitionCount);
for (var i = 0; i < partitionCount; i++)
{
- partitions.Add(ArrayList.Synchronized(new ArrayList()));
+ partitions.Add(new ArrayList());
}
- Parallel.ForEach(m, kvp =>
+ foreach (var kvp in m)
{
ValidationUtil.CheckNotNull(kvp.Key, ValidationUtil.NULL_KEY_IS_NOT_ALLOWED);
ValidationUtil.CheckNotNull(kvp.Value, ValidationUtil.NULL_VALUE_IS_NOT_ALLOWED);
@@ -777,7 +777,7 @@ public void PutAll(IDictionary m)
var partition = (ArrayList) partitions[partitionId];
partition.Add(keyData);
partition.Add(valueData);
- });
+ }
PutAllInternal(m, partitions);
}
diff --git a/Hazelcast.Net/Hazelcast.Client.Spi/ClientClusterService.cs b/Hazelcast.Net/Hazelcast.Client.Spi/ClientClusterService.cs
index 1e9cc39a33..63d2e6a27b 100644
--- a/Hazelcast.Net/Hazelcast.Client.Spi/ClientClusterService.cs
+++ b/Hazelcast.Net/Hazelcast.Client.Spi/ClientClusterService.cs
@@ -48,6 +48,8 @@ internal class ClientClusterService : IClientClusterService, IConnectionListener
private readonly AtomicReference> _membersRef =
new AtomicReference>();
+ private readonly object _initialMembershipListenerMutex = new object();
+
private ClientMembershipListener _clientMembershipListener;
private ClientConnectionManager _connectionManager;
private Address _ownerConnectionAddress;
@@ -58,6 +60,7 @@ internal class ClientClusterService : IClientClusterService, IConnectionListener
public ClientClusterService(HazelcastClient client)
{
+ _membersRef.Set(new Dictionary());
_client = client;
var networkConfig = GetClientConfig().GetNetworkConfig();
@@ -92,6 +95,7 @@ public ClientClusterService(HazelcastClient client)
AddMembershipListenerWithoutInit(membershipListener);
}
}
+
}
private Address OwnerConnectionAddress
@@ -161,15 +165,13 @@ public string AddMembershipListener(IMembershipListener listener)
{
throw new ArgumentNullException("listener");
}
- var id = Guid.NewGuid().ToString();
- _listeners[id] = listener;
- if (listener is IInitialMembershipListener)
+
+ lock (_initialMembershipListenerMutex)
{
- // TODO: needs sync with membership events...
- var cluster = _client.GetCluster();
- ((IInitialMembershipListener) listener).Init(new InitialMembershipEvent(cluster, cluster.GetMembers()));
+ var id = AddMembershipListenerWithoutInit(listener);
+ InitMembershipListener(listener);
+ return id;
}
- return id;
}
public bool RemoveMembershipListener(string registrationId)
@@ -215,7 +217,6 @@ public virtual void Start()
{
Init();
ConnectToCluster();
- InitMembershipListener();
}
internal int ServerVersion
@@ -232,55 +233,42 @@ internal int ServerVersion
}
}
- internal virtual void FireMemberAttributeEvent(MemberAttributeEvent @event)
+ internal void FireMemberAttributeEvent(MemberAttributeEvent @event)
{
- _client.GetClientExecutionService().Submit(() =>
+ foreach (var listener in _listeners.Values)
{
- foreach (var listener in _listeners.Values)
- {
- listener.MemberAttributeChanged(@event);
- }
- });
+ listener.MemberAttributeChanged(@event);
+ }
}
- internal virtual void FireMembershipEvent(MembershipEvent @event)
+ private void FireMembershipEvent(MembershipEvent @event)
{
- _client.GetClientExecutionService().Submit((() =>
+ foreach (var listener in _listeners.Values)
{
- foreach (var listener in _listeners.Values)
+ if (@event.GetEventType() == MembershipEvent.MemberAdded)
{
- if (@event.GetEventType() == MembershipEvent.MemberAdded)
- {
- listener.MemberAdded(@event);
- }
- else
- {
- listener.MemberRemoved(@event);
- }
+ listener.MemberAdded(@event);
}
- }));
- }
-
- internal virtual IDictionary GetMembersRef()
- {
- return _membersRef.Get();
+ else
+ {
+ listener.MemberRemoved(@event);
+ }
+ }
}
- internal virtual string MembersString()
- {
- var sb = new StringBuilder("\n\nMembers [");
- var members = GetMemberList();
- sb.Append(members != null ? members.Count : 0);
- sb.Append("] {");
- if (members != null)
+ private void FireInitialMembershipEvent(InitialMembershipEvent @event) {
+ foreach (var listener in _listeners.Values)
{
- foreach (var member in members)
+ if (listener is IInitialMembershipListener)
{
- sb.Append("\n\t").Append(member);
+ ((IInitialMembershipListener) listener).Init(@event);
}
}
- sb.Append("\n}\n");
- return sb.ToString();
+ }
+
+ internal virtual IDictionary GetMembersRef()
+ {
+ return _membersRef.Get();
}
internal virtual void SetMembersRef(IDictionary map)
@@ -288,10 +276,11 @@ internal virtual void SetMembersRef(IDictionary map)
_membersRef.Set(map);
}
- private void AddMembershipListenerWithoutInit(IMembershipListener listener)
+ private string AddMembershipListenerWithoutInit(IMembershipListener listener)
{
var id = Guid.NewGuid().ToString();
- _listeners[id] = listener;
+ _listeners.TryAdd(id, listener);
+ return id;
}
///
@@ -426,18 +415,53 @@ private void Init()
_connectionManager.AddConnectionListener(this);
}
- private void InitMembershipListener()
+ private void InitMembershipListener(IMembershipListener listener) {
+ if (listener is IInitialMembershipListener) {
+ var cluster = _client.GetCluster();
+ var memberCollection = _membersRef.Get().Values;
+ if (memberCollection.Count == 0)
+ {
+ //if members are empty,it means initial event did not arrive yet
+ //it will be redirected to listeners when it arrives see #handleInitialMembershipEvent
+ return;
+ }
+ var members = new HashSet(memberCollection);
+ var @event = new InitialMembershipEvent(cluster, members);
+ ((IInitialMembershipListener) listener).Init(@event);
+ }
+ }
+
+ internal void HandleInitialMembershipEvent(InitialMembershipEvent @event)
{
- foreach (var membershipListener in _listeners.Values)
+ lock (_initialMembershipListenerMutex)
{
- if (membershipListener is IInitialMembershipListener)
+ var initialMembers = @event.GetMembers();
+ var newMap = new Dictionary();
+ foreach (var initialMember in initialMembers)
{
- // TODO: needs sync with membership events...
- var cluster = _client.GetCluster();
- var @event = new InitialMembershipEvent(cluster, cluster.GetMembers());
- ((IInitialMembershipListener) membershipListener).Init(@event);
+ newMap.Add(initialMember.GetAddress(), initialMember);
+ }
+ _membersRef.Set(newMap);
+ FireInitialMembershipEvent(@event);
+ }
+ }
+
+ internal void HandleMembershipEvent(MembershipEvent @event)
+ {
+ lock (_initialMembershipListenerMutex)
+ {
+ var member = @event.GetMember();
+ var dictionary = _membersRef.Get();
+ var newMap = new Dictionary(dictionary);
+ if (@event.GetEventType() == MembershipEvent.MemberAdded) {
+ newMap.Add(member.GetAddress(), member);
+ } else {
+ newMap.Remove(member.GetAddress());
}
+ _membersRef.Set(newMap);
+ FireMembershipEvent(@event);
}
}
+
}
}
\ No newline at end of file
diff --git a/Hazelcast.Net/Hazelcast.Client.Spi/ClientListenerService.cs b/Hazelcast.Net/Hazelcast.Client.Spi/ClientListenerService.cs
index 7850653e0c..68e62f2126 100644
--- a/Hazelcast.Net/Hazelcast.Client.Spi/ClientListenerService.cs
+++ b/Hazelcast.Net/Hazelcast.Client.Spi/ClientListenerService.cs
@@ -129,8 +129,8 @@ public bool DeregisterListener(string userRegistrationId)
private bool DeregisterListenerInternal(string userRegistrationId)
{
- //This method should not be called from registrationExecutor
- Debug.Assert(Thread.CurrentThread.Name == null || !Thread.CurrentThread.Name.Contains("eventRegistration"));
+ //This method should only be called from registrationExecutor
+ Debug.Assert(Thread.CurrentThread.Name != null && Thread.CurrentThread.Name.Contains("eventRegistration"));
ListenerRegistration listenerRegistration;
if (!_registrations.TryGetValue(userRegistrationId, out listenerRegistration))
{
diff --git a/Hazelcast.Net/Hazelcast.Client.Spi/ClientMembershipListener.cs b/Hazelcast.Net/Hazelcast.Client.Spi/ClientMembershipListener.cs
index 1efadeaae6..e54b1daa0e 100644
--- a/Hazelcast.Net/Hazelcast.Client.Spi/ClientMembershipListener.cs
+++ b/Hazelcast.Net/Hazelcast.Client.Spi/ClientMembershipListener.cs
@@ -13,8 +13,11 @@
// limitations under the License.
using System;
+using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
+using System.Text;
using System.Threading;
using Hazelcast.Client.Connection;
using Hazelcast.Client.Protocol.Codec;
@@ -28,12 +31,12 @@ namespace Hazelcast.Client.Spi
{
internal class ClientMembershipListener
{
- public const int InitialMembersTimeoutSeconds = 5;
+ private const int InitialMembersTimeoutSeconds = 5;
private static readonly ILogger Logger = Logging.Logger.GetLogger(typeof (ClientMembershipListener));
private readonly HazelcastClient _client;
private readonly ClientClusterService _clusterService;
private readonly ClientConnectionManager _connectionManager;
- private readonly IList _members = new List();
+ private readonly ISet _members = new HashSet();
private readonly ClientPartitionService _partitionService;
private ManualResetEventSlim _initialListFetched;
@@ -49,7 +52,7 @@ public virtual void BeforeListenerRegister()
{
}
- public void HandleMember(IMember member, int eventType)
+ private void HandleMember(IMember member, int eventType)
{
switch (eventType)
{
@@ -71,11 +74,10 @@ public void HandleMember(IMember member, int eventType)
break;
}
}
-
_partitionService.RefreshPartitions();
}
- public void HandleMemberAttributeChange(string uuid, string key, int operationType, string value)
+ private void HandleMemberAttributeChange(string uuid, string key, int operationType, string value)
{
var memberMap = _clusterService.GetMembersRef();
if (memberMap == null)
@@ -96,39 +98,42 @@ public void HandleMemberAttributeChange(string uuid, string key, int operationTy
}
}
- public void HandleMemberCollection(ICollection initialMembers)
+ private void HandleMemberCollection(ICollection initialMembers)
{
- var prevMembers = new Dictionary();
+ var prevMembers = new HashSet();
if (_members.Any())
{
- prevMembers = new Dictionary(_members.Count);
- foreach (var member in _members)
- {
- prevMembers[member.GetUuid()] = member;
- }
+ prevMembers = new HashSet(_members);
_members.Clear();
}
foreach (var initialMember in initialMembers)
{
_members.Add(initialMember);
}
-
- var events = DetectMembershipEvents(prevMembers);
- if (events.Count != 0)
+
+ if (prevMembers.Count == 0)
{
- ApplyMemberListChanges();
+ //this means this is the first time client connected to cluster
+ Logger.Info(MembersString());
+ var immutableSetOfMembers = ImmutableSetOfMembers();
+ var cluster = _client.GetCluster();
+ var initialMembershipEvent = new InitialMembershipEvent(cluster, immutableSetOfMembers);
+ _clusterService.HandleInitialMembershipEvent(initialMembershipEvent);
+ _initialListFetched.Set();
+ return;
}
+ var events = DetectMembershipEvents(prevMembers);
+ Logger.Info(MembersString());
FireMembershipEvent(events);
_initialListFetched.Set();
}
- public virtual void OnListenerRegister()
- {
- }
-
- internal virtual void ListenMembershipEvents(Address ownerConnectionAddress)
+ internal void ListenMembershipEvents(Address ownerConnectionAddress)
{
- Logger.Finest("Starting to listen for membership events from " + ownerConnectionAddress);
+ if (Logger.IsFinestEnabled())
+ {
+ Logger.Finest("Starting to listen for membership events from " + ownerConnectionAddress);
+ }
_initialListFetched = new ManualResetEventSlim();
try
{
@@ -148,7 +153,7 @@ internal virtual void ListenMembershipEvents(Address ownerConnectionAddress)
var invocationService = (ClientInvocationService) _client.GetInvocationService();
var future = invocationService.InvokeListenerOnConnection(clientMessage, handler, connection);
var response = ThreadUtil.GetResult(future);
- //registraiton id is ignored as this listener will never be removed
+ //registration id is ignored as this listener will never be removed
var registirationId = ClientAddMembershipListenerCodec.DecodeResponse(response).response;
WaitInitialMemberListFetched();
}
@@ -174,94 +179,71 @@ internal virtual void ListenMembershipEvents(Address ownerConnectionAddress)
}
}
- private void ApplyMemberListChanges()
- {
- UpdateMembersRef();
- Logger.Info(_clusterService.MembersString());
- }
-
- private IList DetectMembershipEvents(IDictionary prevMembers)
- {
- IList events = new List();
- var eventMembers = GetMembers();
+ private IList DetectMembershipEvents(ISet prevMembers) {
+ var events = new List();
+
+ var eventMembers = ImmutableSetOfMembers();
+
+ var newMembers = new LinkedList();
foreach (var member in _members)
{
- IMember former;
- prevMembers.TryGetValue(member.GetUuid(), out former);
- if (former == null)
- {
- events.Add(new MembershipEvent(_client.GetCluster(), member, MembershipEvent.MemberAdded,
- eventMembers));
- }
- else
+ if (!prevMembers.Remove(member))
{
- prevMembers.Remove(member.GetUuid());
+ newMembers.AddLast(member);
}
}
- foreach (var member in prevMembers.Values)
+ // removal events should be added before added events
+ foreach (var member in prevMembers)
{
events.Add(new MembershipEvent(_client.GetCluster(), member, MembershipEvent.MemberRemoved, eventMembers));
var address = member.GetAddress();
if (_clusterService.GetMember(address) == null)
{
var connection = _connectionManager.GetConnection(address);
- if (connection != null)
- {
+ if (connection != null) {
_connectionManager.DestroyConnection(connection, new TargetDisconnectedException(address, "member left the cluster."));
}
}
}
+ foreach (var member in newMembers)
+ {
+ events.Add(new MembershipEvent(_client.GetCluster(), member, MembershipEvent.MemberAdded, eventMembers));
+ }
return events;
}
-
private void FireMembershipEvent(IList events)
{
foreach (var @event in events)
{
- _clusterService.FireMembershipEvent(@event);
+ _clusterService.HandleMembershipEvent(@event);
}
}
- private ICollection GetMembers()
+ private ICollection ImmutableSetOfMembers()
{
- var set = new HashSet();
- foreach (var member in _members)
- {
- set.Add(member);
- }
- return set;
+ return new ReadOnlyCollection(_members.ToList());
}
private void MemberAdded(IMember member)
{
_members.Add(member);
- ApplyMemberListChanges();
- var @event = new MembershipEvent(_client.GetCluster(), member, MembershipEvent.MemberAdded, GetMembers());
- _clusterService.FireMembershipEvent(@event);
+ Logger.Info(MembersString());
+ var @event = new MembershipEvent(_client.GetCluster(), member, MembershipEvent.MemberAdded, ImmutableSetOfMembers());
+ _clusterService.HandleMembershipEvent(@event);
}
private void MemberRemoved(IMember member)
{
_members.Remove(member);
- ApplyMemberListChanges();
+ Logger.Info(MembersString());
var connection = _connectionManager.GetConnection(member.GetAddress());
if (connection != null)
{
_connectionManager.DestroyConnection(connection, new TargetDisconnectedException(member.GetAddress(),
"member left the cluster."));
}
- var @event = new MembershipEvent(_client.GetCluster(), member, MembershipEvent.MemberRemoved, GetMembers());
- _clusterService.FireMembershipEvent(@event);
- }
-
- private void UpdateMembersRef()
- {
- IDictionary map = new Dictionary(_members.Count);
- foreach (var member in _members)
- {
- map[member.GetAddress()] = member;
- }
- _clusterService.SetMembersRef(map);
+ var @event = new MembershipEvent(_client.GetCluster(), member, MembershipEvent.MemberRemoved, ImmutableSetOfMembers());
+ _clusterService.HandleMembershipEvent(@event);
}
///
@@ -274,5 +256,18 @@ private void WaitInitialMemberListFetched()
Logger.Warning("Error while getting initial member list from cluster!");
}
}
+
+ private string MembersString() {
+ var sb = new StringBuilder("\n\nMembers [");
+ sb.Append(_members.Count);
+ sb.Append("] {");
+ foreach (var member in _members)
+ {
+ sb.Append("\n\t").Append(member);
+ }
+ sb.Append("\n}\n");
+ return sb.ToString();
+ }
+
}
}
\ No newline at end of file
diff --git a/Hazelcast.Net/Hazelcast.Core/Member.cs b/Hazelcast.Net/Hazelcast.Core/Member.cs
index cb8db38938..91b0f38a7d 100644
--- a/Hazelcast.Net/Hazelcast.Core/Member.cs
+++ b/Hazelcast.Net/Hazelcast.Core/Member.cs
@@ -100,44 +100,24 @@ public string GetAttribute(string key)
return _out;
}
+ private bool Equals(Member other)
+ {
+ return Equals(_address, other._address) && string.Equals(_uuid, other._uuid);
+ }
+
public override bool Equals(object obj)
{
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (GetType() != obj.GetType())
- {
- return false;
- }
- var other = (Member) obj;
- if (_address == null)
- {
- if (other._address != null)
- {
- return false;
- }
- }
- else
- {
- if (!_address.Equals(other._address))
- {
- return false;
- }
- }
- return true;
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ return obj is Member && Equals((Member) obj);
}
public override int GetHashCode()
{
- var Prime = 31;
- var result = 1;
- result = Prime*result + ((_address == null) ? 0 : _address.GetHashCode());
- return result;
+ unchecked
+ {
+ return ((_address != null ? _address.GetHashCode() : 0) * 397) ^ (_uuid != null ? _uuid.GetHashCode() : 0);
+ }
}
public override string ToString()
diff --git a/Hazelcast.Test/Hazelcast.Client.Test/ClientClusterRestartEventTest.cs b/Hazelcast.Test/Hazelcast.Client.Test/ClientClusterRestartEventTest.cs
new file mode 100644
index 0000000000..6f83a09c88
--- /dev/null
+++ b/Hazelcast.Test/Hazelcast.Client.Test/ClientClusterRestartEventTest.cs
@@ -0,0 +1,128 @@
+// Copyright (c) 2008-2019, Hazelcast, Inc. All Rights Reserved.
+//
+// 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.
+
+using System.Collections.Concurrent;
+using System.Linq;
+using System.Threading;
+using Hazelcast.Core;
+using NUnit.Framework;
+
+namespace Hazelcast.Client.Test
+{
+ [TestFixture]
+ public class ClientClusterRestartEventTest : MultiMemberBaseNoSetupTest
+ {
+ [TearDown]
+ public void Teardown()
+ {
+ ShutdownRemoteController();
+ }
+
+ [Test]
+ public void TestSingleMember()
+ {
+ string oldMemberUUID = null;
+ SetupCluster(() =>
+ {
+ oldMemberUUID = StartNewMember();
+ });
+
+ var memberAdded = new CountdownEvent(1);
+ var memberRemoved = new CountdownEvent(1);
+
+ string addedMemberReferenceUUID = null;
+ string removedMemberReferenceUUID = null;
+
+ Client.GetCluster().AddMembershipListener(new MembershipListener
+ {
+ OnMemberAdded = membershipEvent =>
+ {
+ Interlocked.Exchange(ref addedMemberReferenceUUID, membershipEvent.GetMember().GetUuid());
+ memberAdded.Signal();
+ },
+ OnMemberRemoved = membershipEvent =>
+ {
+ Interlocked.Exchange(ref removedMemberReferenceUUID, membershipEvent.GetMember().GetUuid());
+ memberRemoved.Signal();
+ }
+ });
+
+ ShutdownMember(oldMemberUUID);
+ var newMemberUUID = StartNewMember();
+
+ TestSupport.AssertOpenEventually(memberRemoved);
+ Assert.AreEqual(oldMemberUUID, removedMemberReferenceUUID);
+
+ TestSupport.AssertOpenEventually(memberAdded);
+ Assert.AreEqual(newMemberUUID, addedMemberReferenceUUID);
+
+ var members = Client.GetCluster().GetMembers();
+ Assert.True(members.Any(member => member.GetUuid() == newMemberUUID));
+ Assert.AreEqual(1, members.Count);
+ }
+
+ [Test]
+ public void TestMultiMember()
+ {
+ string oldMemberUUID0 = null;
+ string oldMemberUUID1 = null;
+ SetupCluster(() =>
+ {
+ oldMemberUUID0 = StartNewMember();
+ oldMemberUUID1 = StartNewMember();
+ });
+
+ var memberAdded = new CountdownEvent(2);
+ var memberRemoved = new CountdownEvent(2);
+
+ var addedMemberUUIDs = new ConcurrentBag();
+ var removedMemberUUIDs = new ConcurrentBag();
+
+ Client.GetCluster().AddMembershipListener(new MembershipListener
+ {
+ OnMemberAdded = membershipEvent =>
+ {
+ addedMemberUUIDs.Add(membershipEvent.GetMember().GetUuid());
+ memberAdded.Signal();
+ },
+ OnMemberRemoved = membershipEvent =>
+ {
+ removedMemberUUIDs.Add(membershipEvent.GetMember().GetUuid());
+ memberRemoved.Signal();
+ }
+ });
+ while (!ShutdownCluster())
+ {
+ Thread.Sleep(1000);
+ }
+ var newMemberUUID0 = StartNewMember();
+ var newMemberUUID1 = StartNewMember();
+
+ TestSupport.AssertOpenEventually(memberRemoved);
+ Assert.AreEqual(2, removedMemberUUIDs.Count);
+ Assert.Contains(oldMemberUUID0, removedMemberUUIDs);
+ Assert.Contains(oldMemberUUID1, removedMemberUUIDs);
+
+ TestSupport.AssertOpenEventually(memberAdded);
+ Assert.AreEqual(2, addedMemberUUIDs.Count);
+ Assert.Contains(newMemberUUID0, addedMemberUUIDs);
+ Assert.Contains(newMemberUUID1, addedMemberUUIDs);
+
+ var members = Client.GetCluster().GetMembers();
+ Assert.AreEqual(2, members.Count);
+ Assert.True(members.Any(member => member.GetUuid() == newMemberUUID0));
+ Assert.True(members.Any(member => member.GetUuid() == newMemberUUID1));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Hazelcast.Test/Hazelcast.Client.Test/ClientClusterServiceTest.cs b/Hazelcast.Test/Hazelcast.Client.Test/ClientClusterServiceTest.cs
index a7cd809b69..7b6b03a74a 100644
--- a/Hazelcast.Test/Hazelcast.Client.Test/ClientClusterServiceTest.cs
+++ b/Hazelcast.Test/Hazelcast.Client.Test/ClientClusterServiceTest.cs
@@ -27,9 +27,12 @@ internal class ClientClusterServiceTest : HazelcastTestSupport
private Cluster _cluster;
private RemoteController.Client _remoteController;
+ private InitialMembershipListener _initialMembershipListener;
+
[SetUp]
public void Setup()
{
+ _initialMembershipListener = new InitialMembershipListener();
_remoteController = CreateRemoteController();
_cluster = CreateCluster(_remoteController);
StartMember(_remoteController, _cluster);
@@ -43,7 +46,13 @@ public void TearDown()
_remoteController.shutdownCluster(_cluster.Id);
StopRemoteController(_remoteController);
}
-
+
+ protected override void ConfigureClient(ClientConfig config)
+ {
+ base.ConfigureClient(config);
+ config.AddListenerConfig(new ListenerConfig(_initialMembershipListener));
+ }
+
protected override void ConfigureGroup(ClientConfig config)
{
config.GetGroupConfig().SetName(_cluster.Id).SetPassword(_cluster.Id);
@@ -116,11 +125,26 @@ public void TestInitialMembershipService()
Assert.IsNotNull(member);
Assert.IsNotNull(listener._membershipEvent.GetCluster());
Assert.IsNotNull(listener._membershipEvent.ToString());
+ Assert.AreEqual(1, _initialMembershipListener.counter);
+ }
+
+ [Test]
+ public void TestInitialMembershipWithConfig()
+ {
+ var members = _initialMembershipListener._membershipEvent.GetMembers();
+ Assert.AreEqual(1, members.Count);
+
+ var member = members.FirstOrDefault();
+ Assert.IsNotNull(member);
+ Assert.IsNotNull(_initialMembershipListener._membershipEvent.GetCluster());
+ Assert.IsNotNull(_initialMembershipListener._membershipEvent.ToString());
+ Assert.AreEqual(1, _initialMembershipListener.counter);
}
private class InitialMembershipListener : IInitialMembershipListener
{
public InitialMembershipEvent _membershipEvent;
+ public long counter = 0;
public void MemberAdded(MembershipEvent membershipEvent)
{
@@ -137,6 +161,7 @@ public void MemberAttributeChanged(MemberAttributeEvent memberAttributeEvent)
public void Init(InitialMembershipEvent membershipEvent)
{
_membershipEvent = membershipEvent;
+ Interlocked.Increment(ref counter);
}
}
}
diff --git a/Hazelcast.Test/Hazelcast.Client.Test/ClientMapTest.cs b/Hazelcast.Test/Hazelcast.Client.Test/ClientMapTest.cs
index a634cd94c0..fe54f5709a 100644
--- a/Hazelcast.Test/Hazelcast.Client.Test/ClientMapTest.cs
+++ b/Hazelcast.Test/Hazelcast.Client.Test/ClientMapTest.cs
@@ -469,7 +469,7 @@ public virtual void TestGet()
}
}
- [Test]
+ [Test, Repeat(100)]
public virtual void TestGetAllExtreme()
{
IDictionary