Skip to content
This repository has been archived by the owner on May 25, 2021. It is now read-only.

Fixing issue #74. Clean up the _serverQueue on blacklist; use only _serv... #77

Merged
merged 2 commits into from Oct 11, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
221 changes: 113 additions & 108 deletions src/Connections/RoundRobinServerManager.cs
Expand Up @@ -4,112 +4,117 @@

namespace FluentCassandra.Connections
{
public class RoundRobinServerManager : IServerManager
{
private readonly object _lock = new object();

private List<Server> _servers;
private Queue<Server> _serverQueue;
private HashSet<Server> _blackListed;

public RoundRobinServerManager(IConnectionBuilder builder)
{
_servers = new List<Server>(builder.Servers);
_serverQueue = new Queue<Server>(_servers);
_blackListed = new HashSet<Server>();
}

private bool IsBlackListed(Server server)
{
return _blackListed.Contains(server);
}

#region IServerManager Members

public bool HasNext
{
get { lock (_lock) { return (_serverQueue.Count - _blackListed.Count) > 0; } }
}

public Server Next()
{
Server server;

lock (_lock)
{
do
{
server = _serverQueue.Dequeue();

if (IsBlackListed(server))
server = null;
else
_serverQueue.Enqueue(server);
}
while (_serverQueue.Count > 0 && server == null);
}

return server;
}

public void Add(Server server)
{
lock (_lock)
{
_servers.Add(server);
_serverQueue.Enqueue(server);
}
}

public void ErrorOccurred(Server server, Exception exc = null)
{
Debug.WriteLineIf(exc != null, exc, "connection");
BlackList(server);
}

public void BlackList(Server server)
{
Debug.WriteLine(server + " has been blacklisted", "connection");
lock (_lock)
{
_blackListed.Add(server);
}
}

public void Remove(Server server)
{
lock (_lock)
{
_servers.Remove(server);
_serverQueue = new Queue<Server>();
_blackListed.RemoveWhere(x => x == server);

foreach (var s in _servers)
{
if (!_blackListed.Contains(s))
_serverQueue.Enqueue(s);
}
}
}

#endregion

#region IEnumerable<Server> Members

public IEnumerator<Server> GetEnumerator()
{
return _servers.GetEnumerator();
}

#endregion

#region IEnumerable Members

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

#endregion
}
public class RoundRobinServerManager : IServerManager
{
private readonly object _lock = new object();

private List<Server> _servers;
private Queue<Server> _serverQueue;
private HashSet<Server> _blackListed;

public RoundRobinServerManager(IConnectionBuilder builder)
{
_servers = new List<Server>(builder.Servers);
_serverQueue = new Queue<Server>(_servers);
_blackListed = new HashSet<Server>();
}

private bool IsBlackListed(Server server)
{
return _blackListed.Contains(server);
}

#region IServerManager Members

public bool HasNext
{
get { lock (_lock) { return _serverQueue.Count > 0; } }
}

public Server Next()
{
Server server = null;

lock (_lock)
{
if (_serverQueue.Count > 0)
{
server = _serverQueue.Dequeue();
_serverQueue.Enqueue(server);
}
}

return server;
}

public void Add(Server server)
{
lock (_lock)
{
_servers.Add(server);
_serverQueue.Enqueue(server);
}
}

public void ErrorOccurred(Server server, Exception exc = null)
{
Debug.WriteLineIf(exc != null, exc, "connection");
BlackList(server);
}

public void BlackList(Server server)
{
Debug.WriteLine(server + " has been blacklisted", "connection");
lock (_lock)
{
if (_blackListed.Add(server))
{
_serverQueue.Clear();
foreach (Server srv in _servers)
{
if (!IsBlackListed(srv))
{
_serverQueue.Enqueue(srv);
}
}
}
}
}

public void Remove(Server server)
{
lock (_lock)
{
_servers.Remove(server);
_serverQueue = new Queue<Server>();
_blackListed.RemoveWhere(x => x == server);

foreach (var s in _servers)
{
if (!_blackListed.Contains(s))
_serverQueue.Enqueue(s);
}
}
}

#endregion

#region IEnumerable<Server> Members

public IEnumerator<Server> GetEnumerator()
{
return _servers.GetEnumerator();
}

#endregion

#region IEnumerable Members

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

#endregion
}
}
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using Xunit;

namespace FluentCassandra.Connections.Tests
{
public class RoundRobinServerManagerTests
{
[Fact]
public void CanBlackListAndCleanQueueTest()
{
RoundRobinServerManager target = new RoundRobinServerManager(new ConnectionBuilder("Server=unit-test-1,unit-test-2,unit-test-3"));

Server srv = new Server("unit-test-4");
target.Add(srv);

bool gotServer4 = false;

for (int i = 0; i < 4; i++)
{
Server server = target.Next();
if (server.ToString().Equals(srv.ToString(), StringComparison.OrdinalIgnoreCase))
{
gotServer4 = true;
break;
}
}

Assert.True(gotServer4);

target.BlackList(srv);

gotServer4 = false;
for (int i = 0; i < 4; i++)
{
Server server = target.Next();
if (server.Equals(srv))
{
gotServer4 = true;
break;
}
}

Assert.False(gotServer4);
}

[Fact]
public void HasNextWithMoreThanHalfBlacklistedTest()
{
RoundRobinServerManager target = new RoundRobinServerManager(new ConnectionBuilder("Server=unit-test-1"));

Server srv1 = null;
Server srv2 = new Server("unit-test-2");
Server srv3 = new Server("unit-test-3");
Server srv4 = new Server("unit-test-4");
target.Add(srv2);
target.Add(srv3);
target.Add(srv4);
List<Server> servers = new List<Server> { new Server("unit-test-1"), srv2, srv3, srv4 };

for (int i = 0; i < 4; i++)
{
Server srv = target.Next();
Assert.True(servers[i].ToString().Equals(srv.ToString(), StringComparison.OrdinalIgnoreCase));
if(i == 0)
{
srv1 = srv;
}
}

target.BlackList(srv2);
target.BlackList(srv3);
Assert.True(target.HasNext);

target.BlackList(srv1);
Assert.True(target.HasNext);

target.BlackList(srv4);
Assert.False(target.HasNext);
}
}
}
1 change: 1 addition & 0 deletions test/FluentCassandra.Tests/FluentCassandra.Tests.csproj
Expand Up @@ -62,6 +62,7 @@
<Compile Include="Connections\ConnectionBuilderTests.cs" />
<Compile Include="Connections\ConnectionProviderTests.cs" />
<Compile Include="Connections\NormalConnectionProviderTests.cs" />
<Compile Include="Connections\RoundRobinServerManagerTests.cs" />
<Compile Include="CqlHelperTest.cs" />
<Compile Include="Helper.cs" />
<Compile Include="Linq\LinqToCqlObjectsCassandraTests.cs" />
Expand Down