├── .gitignore ├── RaftDemo ├── Resources │ ├── Entypo.ttf │ ├── Entypo-license.txt │ └── WindowsIcons-license.txt ├── Views │ ├── Actors │ │ ├── broker.png │ │ ├── DiagramNodeBrokerView.xaml │ │ ├── ClientView.xaml.cs │ │ ├── DiagramNodeBrokerView.xaml.cs │ │ ├── ClientView.xaml │ │ └── ServerView.xaml.cs │ ├── AttachDescriptorFromView.xaml │ ├── LogEntryView.xaml.cs │ ├── AppView.xaml.cs │ ├── SimulationSettingsView.xaml.cs │ ├── AttachDescriptorToView.xaml.cs │ ├── AttachDescriptorFromView.xaml.cs │ ├── AttachDescriptorToView.xaml │ ├── LogEntryView.xaml │ ├── AppView.xaml │ └── SimulationSettingsView.xaml ├── ViewModels │ ├── AppViewModel.cs │ ├── IShell.cs │ ├── AttachDescriptorToViewModel.cs │ ├── AttachDescriptorFromViewModel.cs │ ├── Actors │ │ ├── BrokerViewModel.cs │ │ ├── ClientViewModel.cs │ │ └── ActorViewModel.cs │ ├── ClientToServerConnectionViewModel.cs │ ├── ServerToServerConnectionViewModel.cs │ └── LogEntryViewModel.cs ├── FodyWeavers.xml ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ └── Resources.Designer.cs ├── Model │ ├── DiagramNodeBroker.cs │ ├── DiagramNodeClient.cs │ ├── DiagramNodeServer.cs │ ├── Messages.cs │ ├── RaftSoundPlayer.cs │ ├── RaftClient.cs │ ├── SimulationSettings.cs │ └── RaftHost.cs ├── NodeSoftware │ ├── OutboundMessage.cs │ ├── InboundMessage.cs │ └── TimeoutTimer.cs ├── App.xaml.cs ├── packages.config ├── App.config ├── Converters │ ├── BooleanToOpacityConverter.cs │ ├── RaftStateToStyle.cs │ └── RaftStateToColorConverter.cs ├── App.xaml └── AppBootstrapper.cs ├── Report20150128-1922 — skrót.lnk ├── RaftAlgorithm ├── Messages │ ├── RaftMessageBase.cs │ ├── RequestVote.cs │ ├── RequestVoteResult.cs │ ├── ClientRequestRPC.cs │ ├── AppendEntriesResult.cs │ └── AppendEntriesRPC.cs ├── IRaftEventListener.cs ├── RaftNodeState.cs ├── IRaftNodeSettings.cs ├── LogEntry.cs ├── Properties │ └── AssemblyInfo.cs ├── States │ ├── RaftStateBase.cs │ ├── Leader.cs │ ├── Follower.cs │ └── Candicate.cs ├── RaftAlgorithm.csproj └── RaftEventResult.cs ├── RaftDemo.Tests ├── Images │ ├── UnitTestLogo.scale-100.png │ ├── UnitTestSmallLogo.scale-100.png │ ├── UnitTestStoreLogo.scale-100.png │ └── UnitTestSplashScreen.scale-100.png ├── UnitTest1.cs ├── Properties │ └── AssemblyInfo.cs └── Package.appxmanifest ├── ActorTest ├── packages.config ├── TestClientActor.cs ├── TestServerActor.cs └── Properties │ └── AssemblyInfo.cs ├── NetworkTest ├── packages.config ├── Properties │ └── AssemblyInfo.cs └── SchedlulerTest.cs ├── TaskSchedulerRun ├── App.config ├── Properties │ └── AssemblyInfo.cs ├── Program.cs ├── TsTest.cs ├── TaskSchedulerRun.csproj └── HighPrecisionTimer.cs ├── CaliDiagram ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ └── Resources.Designer.cs ├── packages.config ├── IConnectorSideStrategy.cs ├── Commands │ ├── MoveNodeCommand.cs │ ├── DiagramCommand.cs │ ├── RemoveNodeCommand.cs │ ├── AddNodeCommand.cs │ └── AddConnectionCommand.cs ├── ViewModels │ ├── DiagramBatchMode.cs │ ├── AttachSides.cs │ ├── AttachPoint.cs │ └── DiagramHelpers.cs ├── Views │ ├── EdgeView.xaml │ ├── NodeBaseView.xaml │ ├── DiagramView.xaml.cs │ ├── EdgeView.xaml.cs │ └── DiagramView.xaml ├── Model │ ├── DiagramNodeBase.cs │ ├── DiagramConnection.cs │ └── DiagramModel.cs ├── CaliDiagramHelpers.cs ├── DefaultConnectionStrategy.cs └── Serialization │ ├── XmlSettings.cs │ └── DiagramXmlSerializer.cs ├── NetworkModel ├── Actors │ ├── ActorTimer.cs │ ├── ActorEvents │ │ ├── ActorEventBase.cs │ │ ├── ActorEventType.cs │ │ ├── TimerElapsedEvent.cs │ │ ├── ChannelAddedEvent.cs │ │ ├── ChannelRemovedEvent.cs │ │ └── MessageReceivedEvent.cs │ ├── ActorChannel.cs │ ├── ClientActor.cs │ ├── ActorBase.VirtualFunctions.cs │ ├── ActorState.cs │ ├── ServerActor.cs │ └── ActorBase.cs ├── ConnectionState.cs ├── ChannelType.cs ├── NetworkNode.cs ├── InProcNetwork │ ├── TaskScheduling │ │ ├── TaskSchedulerTask.cs │ │ └── TaskScheduler.cs │ ├── SocketId.cs │ ├── InProcServer.cs │ └── InProcNetwork.cs ├── INetworkModel.cs ├── Properties │ └── AssemblyInfo.cs ├── INetworkSocket.cs ├── NetworkClientState.cs ├── INetworkServer.cs └── NetworkModel.csproj ├── DiagramDesigner.sln └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | pack 2 | packages 3 | */obj/ 4 | */bin/ 5 | *.suo 6 | -------------------------------------------------------------------------------- /RaftDemo/Resources/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/RaftDemo/Resources/Entypo.ttf -------------------------------------------------------------------------------- /Report20150128-1922 — skrót.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/Report20150128-1922 — skrót.lnk -------------------------------------------------------------------------------- /RaftDemo/Views/Actors/broker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/RaftDemo/Views/Actors/broker.png -------------------------------------------------------------------------------- /RaftDemo/ViewModels/AppViewModel.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/RaftDemo/ViewModels/AppViewModel.cs -------------------------------------------------------------------------------- /RaftDemo/ViewModels/IShell.cs: -------------------------------------------------------------------------------- 1 | namespace RaftDemo 2 | { 3 | public interface IShell 4 | { 5 | void Close(); 6 | } 7 | } -------------------------------------------------------------------------------- /RaftAlgorithm/Messages/RaftMessageBase.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RaftAlgorithm.Messages 3 | { 4 | public class RaftMessageBase 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /RaftDemo.Tests/Images/UnitTestLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/RaftDemo.Tests/Images/UnitTestLogo.scale-100.png -------------------------------------------------------------------------------- /RaftDemo.Tests/Images/UnitTestSmallLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/RaftDemo.Tests/Images/UnitTestSmallLogo.scale-100.png -------------------------------------------------------------------------------- /RaftDemo.Tests/Images/UnitTestStoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/RaftDemo.Tests/Images/UnitTestStoreLogo.scale-100.png -------------------------------------------------------------------------------- /RaftDemo/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ActorTest/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /RaftDemo.Tests/Images/UnitTestSplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toomasz/CaliDiagram/HEAD/RaftDemo.Tests/Images/UnitTestSplashScreen.scale-100.png -------------------------------------------------------------------------------- /NetworkTest/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /RaftAlgorithm/IRaftEventListener.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RaftAlgorithm 3 | { 4 | public interface IRaftEventListener 5 | { 6 | void OnElectionStarted(); 7 | void OnAppendEntries(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /RaftDemo/Resources/Entypo-license.txt: -------------------------------------------------------------------------------- 1 | Entypo (http://www.entypo.com/) is created by Daniel Bruce and released under the Creative Commons, Share Alike/Attribution license. 2 | 3 | http://creativecommons.org/licenses/by-sa/3.0/ -------------------------------------------------------------------------------- /TaskSchedulerRun/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RaftAlgorithm/RaftNodeState.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RaftAlgorithm 3 | { 4 | public enum RaftNodeState 5 | { 6 | Booting, 7 | Follower, 8 | Candidate, 9 | Leader 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /RaftDemo/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /CaliDiagram/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /CaliDiagram/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /RaftDemo/Model/DiagramNodeBroker.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.Model; 2 | using System.Runtime.Serialization; 3 | 4 | namespace RaftDemo.Model 5 | { 6 | [DataContract] 7 | class DiagramNodeBroker : DiagramNodeBase 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /RaftDemo/Model/DiagramNodeClient.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.Model; 2 | using System.Runtime.Serialization; 3 | 4 | namespace RaftDemo.Model 5 | { 6 | [DataContract] 7 | class DiagramNodeClient : DiagramNodeBase 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /RaftDemo/Model/DiagramNodeServer.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.Model; 2 | using System.Runtime.Serialization; 3 | 4 | namespace RaftDemo.Model 5 | { 6 | [DataContract] 7 | class DiagramNodeServer:DiagramNodeBase 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors 8 | { 9 | public class ActorTimer 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /RaftDemo/NodeSoftware/OutboundMessage.cs: -------------------------------------------------------------------------------- 1 | 2 | using NetworkModel; 3 | namespace RaftDemo.NodeSoftware 4 | { 5 | public class OutboundMessage 6 | { 7 | public INetworkSocket DestinationChannel { get; set; } 8 | public object Message { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CaliDiagram/IConnectorSideStrategy.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | 3 | namespace CaliDiagram 4 | { 5 | /// 6 | /// Connector placement behaviour 7 | /// 8 | public interface IConnectorSideStrategy 9 | { 10 | AttachSides GetSidesForConnection(ConnectionViewModel connection); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/AttachDescriptorToViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using CaliDiagram.ViewModels; 7 | 8 | namespace RaftDemo.ViewModels 9 | { 10 | class AttachDescriptorToViewModel : NodeBaseViewModel 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/AttachDescriptorFromViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using CaliDiagram.ViewModels; 7 | 8 | namespace RaftDemo.ViewModels 9 | { 10 | public class AttachDescriptorFromViewModel: NodeBaseViewModel 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RaftAlgorithm/Messages/RequestVote.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RaftAlgorithm.Messages 3 | { 4 | public class RequestVote : RaftMessageBase 5 | { 6 | public string CandidateId { get; set; } 7 | public int CandidateTerm { get; set; } 8 | public override string ToString() 9 | { 10 | return "RV"; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorEvents/ActorEventBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors.ActorEvents 8 | { 9 | public abstract class ActorEventBase 10 | { 11 | public abstract ActorEventType EventType { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RaftDemo/NodeSoftware/InboundMessage.cs: -------------------------------------------------------------------------------- 1 | 2 | using NetworkModel; 3 | namespace RaftDemo.NodeSoftware 4 | { 5 | /// 6 | /// Message origination from another component 7 | /// 8 | public class InboundMessage 9 | { 10 | public INetworkSocket SourceChannel { get; set; } 11 | public object Message { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NetworkModel/ConnectionState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel 8 | { 9 | public enum ConnectionState 10 | { 11 | Closed, 12 | Connecting, 13 | Established, 14 | ConnectionFailed, 15 | Closing 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RaftDemo.Tests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 6 | 7 | namespace RaftDemo.Tests 8 | { 9 | [TestClass] 10 | public class UnitTest1 11 | { 12 | [TestMethod] 13 | public void TestMethod1() 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorEvents/ActorEventType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors.ActorEvents 8 | { 9 | public enum ActorEventType 10 | { 11 | ChannelAdded, 12 | ChannelRemoved, 13 | MessageReceived, 14 | TimerElapsed 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorChannel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors 8 | { 9 | public class ActorChannel 10 | { 11 | public ActorChannel(INetworkSocket Socket) 12 | { 13 | this.Socket = Socket; 14 | } 15 | public INetworkSocket Socket { get; private set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/Actors/BrokerViewModel.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace RaftDemo.ViewModels.Actors 9 | { 10 | public class BrokerViewModel: NodeBaseViewModel 11 | { 12 | public BrokerViewModel(string name) 13 | { 14 | this.Name = name; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CaliDiagram/Commands/MoveNodeCommand.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | 3 | namespace CaliDiagram.Commands 4 | { 5 | class MoveNodeCommand : DiagramCommand 6 | { 7 | public MoveNodeCommand(DiagramViewModel diagram):base(diagram) 8 | { 9 | Description = "Move"; 10 | } 11 | 12 | public override void OnSelected() 13 | { 14 | Diagram.HelpText = "Drag and drop nodes!"; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RaftDemo/Model/Messages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RaftDemo.Model 8 | { 9 | public class Message 10 | { 11 | public Message(string op) 12 | { 13 | this.Operation = op; 14 | } 15 | public string Operation 16 | { 17 | get; 18 | private set; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /RaftAlgorithm/IRaftNodeSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RaftAlgorithm 8 | { 9 | public interface IRaftNodeSettings 10 | { 11 | int ClusterSize { get; } 12 | int LeaderTimeoutFrom { get; } 13 | int LeaderTimeoutTo { get; } 14 | 15 | int FollowerTimeoutFrom { get; } 16 | int FollowerTimeoutTo { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CaliDiagram/ViewModels/DiagramBatchMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CaliDiagram.ViewModels 4 | { 5 | public class DiagramBatchMode: IDisposable 6 | { 7 | private DiagramViewModel diagram; 8 | public DiagramBatchMode(DiagramViewModel diagram) 9 | { 10 | this.diagram = diagram; 11 | diagram.IsInBatchMode = true; 12 | } 13 | 14 | public void Dispose() 15 | { 16 | diagram.IsInBatchMode = false; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /RaftAlgorithm/Messages/RequestVoteResult.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RaftAlgorithm.Messages 3 | { 4 | public class RequestVoteResponse : RaftMessageBase 5 | { 6 | public bool VoteGranted { get; set; } 7 | public int CurrentTerm { get; set; } 8 | public string VoterId { get; set; } 9 | 10 | public override string ToString() 11 | { 12 | if (VoteGranted) 13 | return "Yes"; 14 | else 15 | return "No"; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ClientActor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors 8 | { 9 | /// 10 | /// NetworkClient actor can only make connection to server actors 11 | /// 12 | public class ClientActor : ActorBase 13 | { 14 | public ClientActor(INetworkModel networkModel) 15 | :base(networkModel) 16 | { 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ActorTest/TestClientActor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NetworkModel; 7 | using NetworkModel.Actors; 8 | 9 | namespace ActorTest 10 | { 11 | public class TestClientActor: ClientActor 12 | { 13 | public TestClientActor(INetworkModel networkModel) : base(networkModel) 14 | { 15 | } 16 | 17 | public void BroadcastMessage(object message) 18 | { 19 | 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CaliDiagram/Views/EdgeView.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RaftAlgorithm/Messages/ClientRequestRPC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RaftAlgorithm.Messages 8 | { 9 | public class ClientRequestRPC : RaftMessageBase 10 | { 11 | public TMessageType Message 12 | { 13 | get; 14 | set; 15 | } 16 | public ulong SequenceNumber 17 | { 18 | get; 19 | set; 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /RaftDemo/Views/Actors/DiagramNodeBrokerView.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NetworkModel/ChannelType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel 8 | { 9 | public enum ChannelType 10 | { 11 | /// 12 | /// NetworkClient side channel 13 | /// 14 | Client, 15 | /// 16 | /// Server side channel 17 | /// 18 | Server, 19 | /// 20 | /// Listening channel 21 | /// 22 | Listening 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CaliDiagram/Model/DiagramNodeBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace CaliDiagram.Model 10 | { 11 | /// 12 | /// Base diagram node base 13 | /// 14 | [DataContract] 15 | public class DiagramNodeBase 16 | { 17 | 18 | [DataMember] 19 | public Point Location { get; set; } 20 | [DataMember] 21 | public string Name { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ActorTest/TestServerActor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NetworkModel; 7 | using NetworkModel.Actors; 8 | 9 | namespace ActorTest 10 | { 11 | public class TestServerActor: ServerActor 12 | { 13 | public TestServerActor(INetworkModel networkModel, string address) : base(networkModel, address) 14 | { 15 | } 16 | 17 | protected override void OnMessageReceived(ActorChannel channel, object message) 18 | { 19 | 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /RaftDemo/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace RaftDemo 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | public App() 17 | { 18 | InitializeComponent(); 19 | AppBootstrapper bootstrapper = new AppBootstrapper(); 20 | bootstrapper.Initialize(); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CaliDiagram/Model/DiagramConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CaliDiagram.Model 9 | { 10 | /// 11 | /// Diagram connection 12 | /// 13 | [DataContract] 14 | public class DiagramConnection 15 | { 16 | public DiagramConnection() 17 | { 18 | 19 | } 20 | [DataMember] 21 | public DiagramNodeBase From { get; set; } 22 | [DataMember] 23 | public DiagramNodeBase To { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CaliDiagram/ViewModels/AttachSides.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace CaliDiagram.ViewModels 3 | { 4 | /// 5 | /// Represents side pair used to determine connection attach points sides 6 | /// 7 | public class AttachSides 8 | { 9 | public AttachSides(AttachDirection fromSide, AttachDirection toSide) 10 | { 11 | FromSide = fromSide; 12 | ToSide = toSide; 13 | } 14 | public AttachDirection FromSide 15 | { 16 | get; 17 | private set; 18 | } 19 | public AttachDirection ToSide 20 | { 21 | get; 22 | private set; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorEvents/TimerElapsedEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors.ActorEvents 8 | { 9 | public class TimerElapsedEvent: ActorEventBase 10 | { 11 | public TimerElapsedEvent(ActorTimer timer) 12 | { 13 | Timer = timer; 14 | } 15 | public override ActorEventType EventType 16 | { 17 | get 18 | { 19 | return ActorEventType.TimerElapsed; 20 | } 21 | } 22 | public ActorTimer Timer { get; private set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorEvents/ChannelAddedEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors.ActorEvents 8 | { 9 | public class ChannelAddedEvent : ActorEventBase 10 | { 11 | public ChannelAddedEvent(ActorChannel channel) 12 | { 13 | Channel = channel; 14 | } 15 | public override ActorEventType EventType 16 | { 17 | get 18 | { 19 | return ActorEventType.ChannelAdded; 20 | } 21 | } 22 | public ActorChannel Channel { get; private set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorEvents/ChannelRemovedEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors.ActorEvents 8 | { 9 | public class ChannelRemovedEvent : ActorEventBase 10 | { 11 | public ChannelRemovedEvent(ActorChannel channel) 12 | { 13 | Channel = channel; 14 | } 15 | public override ActorEventType EventType 16 | { 17 | get 18 | { 19 | return ActorEventType.ChannelRemoved; 20 | } 21 | } 22 | public ActorChannel Channel { get ; private set;} 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CaliDiagram/Commands/DiagramCommand.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | using System.Windows; 3 | 4 | namespace CaliDiagram.Commands 5 | { 6 | public class DiagramCommand 7 | { 8 | protected readonly DiagramViewModel Diagram; 9 | public DiagramCommand(DiagramViewModel diagram) 10 | { 11 | this.Diagram = diagram; 12 | } 13 | public virtual string Description { get; set; } 14 | 15 | public virtual void HandleNodeClick(NodeBaseViewModel node) { } 16 | public virtual void HandleConnectionClick(ConnectionViewModel node) { } 17 | public virtual void HandleDiagramClick(Point location) { } 18 | public virtual void OnSelected() { } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /RaftAlgorithm/LogEntry.cs: -------------------------------------------------------------------------------- 1 | namespace RaftAlgorithm 2 | { 3 | public class LogEntry 4 | { 5 | public LogEntry(int commitIndex, int term, T data) 6 | { 7 | CommitIndex = commitIndex; 8 | Term = term; 9 | Data = data; 10 | } 11 | public override string ToString() 12 | { 13 | return Data.ToString(); 14 | } 15 | public T Data 16 | { 17 | get; 18 | set; 19 | } 20 | public int CommitIndex 21 | { 22 | get; 23 | set; 24 | } 25 | public int Term 26 | { 27 | get; 28 | set; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CaliDiagram/Views/NodeBaseView.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /NetworkModel/NetworkNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel 8 | { 9 | public class NetworkNode 10 | { 11 | public NetworkNode(string name, INetworkModel network) 12 | { 13 | this.Network = network; 14 | this.Name = name; 15 | Init(); 16 | } 17 | void Init() 18 | { 19 | Server = Network.CreateServer(Name); 20 | } 21 | INetworkServer Server { get; set; } 22 | INetworkModel Network { get; set; } 23 | public string Name 24 | { 25 | get; 26 | private set; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /RaftDemo/Views/AttachDescriptorFromView.xaml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /RaftDemo/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CaliDiagram/Model/DiagramModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CaliDiagram.Model 9 | { 10 | /// 11 | /// Base diagram model used for saving diagram 12 | /// 13 | [DataContract] 14 | public class DiagramModel 15 | { 16 | public DiagramModel() 17 | { 18 | Nodes = new List(); 19 | Edges = new List(); 20 | } 21 | [DataMember] 22 | public List Nodes { get; private set; } 23 | [DataMember] 24 | public List Edges { get; private set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RaftDemo/Views/LogEntryView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RaftDemo.Views 17 | { 18 | /// 19 | /// Interaction logic for LogEntryView.xaml 20 | /// 21 | public partial class LogEntryView : UserControl 22 | { 23 | public LogEntryView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RaftDemo/Views/AppView.xaml.cs: -------------------------------------------------------------------------------- 1 | using MahApps.Metro.Controls; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace RaftDemo 18 | { 19 | /// 20 | /// Interaction logic for AppView.xaml 21 | /// 22 | public partial class AppView : MetroWindow 23 | { 24 | public AppView() 25 | { 26 | InitializeComponent(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /RaftDemo/Views/Actors/ClientView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RaftDemo.Views.Actors 17 | { 18 | /// 19 | /// Interaction logic for DiagramNodeSmallView.xaml 20 | /// 21 | public partial class ClientView : UserControl 22 | { 23 | public ClientView() 24 | { 25 | InitializeComponent(); 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorEvents/MessageReceivedEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors.ActorEvents 8 | { 9 | public class MessageReceivedEvent : ActorEventBase 10 | { 11 | public MessageReceivedEvent(ActorChannel channel, object message) 12 | { 13 | Message = message; 14 | Channel = channel; 15 | } 16 | 17 | public override ActorEventType EventType 18 | { 19 | get 20 | { 21 | return ActorEventType.MessageReceived; 22 | } 23 | } 24 | public ActorChannel Channel { get; private set; } 25 | public object Message { get; private set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /RaftDemo/Views/SimulationSettingsView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RaftDemo.Views 17 | { 18 | /// 19 | /// Interaction logic for WorldSettingsView.xaml 20 | /// 21 | public partial class SimulationSettingsView : UserControl 22 | { 23 | public SimulationSettingsView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RaftDemo/Views/AttachDescriptorToView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RaftDemo.Views 17 | { 18 | /// 19 | /// Interaction logic for AttachDescriptorToView.xaml 20 | /// 21 | public partial class AttachDescriptorToView : UserControl 22 | { 23 | public AttachDescriptorToView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RaftDemo/Views/Actors/DiagramNodeBrokerView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RaftDemo.Views.Actors 17 | { 18 | /// 19 | /// Interaction logic for DiagramNodeBroker.xaml 20 | /// 21 | public partial class DiagramNodeBrokerView : UserControl 22 | { 23 | public DiagramNodeBrokerView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorBase.VirtualFunctions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NetworkModel.Actors.ActorEvents; 7 | 8 | namespace NetworkModel.Actors 9 | { 10 | public partial class ActorBase 11 | { 12 | protected virtual void OnInitialized() { } 13 | protected virtual void OnDestroyed() { } 14 | protected virtual void OnChannelCreated(ActorChannel channel) { } 15 | protected virtual void OnChannelRemoved(ActorChannel channel) { } 16 | protected virtual void OnMessageReceived(ActorChannel channel, object message) { } 17 | protected virtual void OnCommandReceived(string command) { } 18 | 19 | 20 | public event EventHandler ActorEvent; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /RaftDemo/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /RaftDemo/Views/AttachDescriptorFromView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace RaftDemo.Views 17 | { 18 | /// 19 | /// Interaction logic for AttachDescriptorFromView.xaml 20 | /// 21 | public partial class AttachDescriptorFromView : UserControl 22 | { 23 | public AttachDescriptorFromView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RaftDemo/Views/AttachDescriptorToView.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /CaliDiagram/Commands/RemoveNodeCommand.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | 3 | namespace CaliDiagram.Commands 4 | { 5 | class RemoveNodeCommand : DiagramCommand 6 | { 7 | public RemoveNodeCommand(DiagramViewModel diagram, string description) 8 | : base(diagram) 9 | { 10 | this.Description = description; 11 | } 12 | 13 | public override void OnSelected() 14 | { 15 | Diagram.HelpText = "Remove any node by clicking it."; 16 | } 17 | public override void HandleNodeClick(NodeBaseViewModel node) 18 | { 19 | Diagram.RemoveNode(node); 20 | } 21 | 22 | public override void HandleConnectionClick(ConnectionViewModel connection) 23 | { 24 | Diagram.RemoveConnection(connection); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors 8 | { 9 | public enum ActorState 10 | { 11 | /// 12 | /// Actor is stopped 13 | /// 14 | Stopped, 15 | /// 16 | /// Actor is booting up 17 | /// 18 | Starting, 19 | /// 20 | /// Actor is running 21 | /// 22 | Started, 23 | /// 24 | /// Actor is shutting down 25 | /// 26 | Stopping, 27 | /// 28 | /// Unrecoverable error occured during actor operation 29 | /// 30 | Error 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /RaftDemo/Model/RaftSoundPlayer.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm; 2 | using RaftDemo.Model; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace RaftDemo.Model 10 | { 11 | public class RaftSoundPlayer: IRaftEventListener 12 | { 13 | SimulationSettings worldSettings; 14 | public RaftSoundPlayer(SimulationSettings worldSettings) 15 | { 16 | this.worldSettings = worldSettings; 17 | } 18 | public void OnElectionStarted() 19 | { 20 | if (worldSettings.SoundEnabled) 21 | Console.Beep(); 22 | } 23 | 24 | public void OnAppendEntries() 25 | { 26 | if(worldSettings.SoundEnabled) 27 | Console.Beep(400, 10); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CaliDiagram/Commands/AddNodeCommand.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | using System.Windows; 3 | 4 | namespace CaliDiagram.Commands 5 | { 6 | class AddNodeCommand : DiagramCommand 7 | { 8 | NodeTypeBehaviour nodeBehaviour; 9 | public AddNodeCommand(DiagramViewModel diagram, string description, NodeTypeBehaviour nodeTypeBehaviour):base(diagram) 10 | { 11 | this.Description = description; 12 | this.nodeBehaviour = nodeTypeBehaviour; 13 | 14 | } 15 | public override void OnSelected() 16 | { 17 | Diagram.HelpText = Description = string.Format("Add {0} node", nodeBehaviour.Name); 18 | } 19 | public override void HandleDiagramClick(Point location) 20 | { 21 | Diagram.AddNode(nodeBehaviour.CreateNode(location), location); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /RaftDemo/Converters/BooleanToOpacityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Data; 7 | 8 | namespace RaftDemo.Converters 9 | { 10 | public class BooleanToOpacityConverter:IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 13 | { 14 | bool boolValue = (bool)value; 15 | if (boolValue == true) 16 | return 1.0; 17 | else 18 | return 0.3; 19 | } 20 | 21 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 22 | { 23 | return null; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/ClientToServerConnectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using CaliDiagram.ViewModels; 8 | using RaftDemo.Model; 9 | 10 | namespace RaftDemo.ViewModels 11 | { 12 | public class ClientToServerConnectionViewModel: ConnectionViewModel 13 | { 14 | public ClientToServerConnectionViewModel(NodeBaseViewModel from, NodeBaseViewModel to, SimulationSettings worldSettings) : 15 | base(from, to) 16 | { 17 | StrokeThickness = 2; 18 | this.worldSettings = worldSettings; 19 | } 20 | SimulationSettings worldSettings; 21 | public override double Latency 22 | { 23 | get 24 | { 25 | return worldSettings.ClientToServerLatency; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /NetworkModel/InProcNetwork/TaskScheduling/TaskSchedulerTask.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.InProcNetwork.TaskScheduling 8 | { 9 | public class TaskSchedlulerTask 10 | { 11 | public DateTime SchedluledTime { get; set; } 12 | public TimeSpan ExecuteAfter { get; set; } 13 | public Action Function { get; set; } 14 | /// 15 | /// Get milliseconds from DateTime.Now to task execution 16 | /// 17 | public DateTime RunTime 18 | { 19 | get 20 | { 21 | return SchedluledTime + ExecuteAfter; 22 | } 23 | } 24 | public int RunIn 25 | { 26 | get 27 | { 28 | int runIn = Convert.ToInt32((RunTime - DateTime.Now).TotalMilliseconds); 29 | if (runIn < 0) 30 | runIn = 0; 31 | return runIn; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /RaftDemo.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RaftDemo.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RaftDemo.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | -------------------------------------------------------------------------------- /RaftDemo/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.0 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RaftDemo.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CaliDiagram/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.0 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CaliDiagram.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RaftAlgorithm/Messages/AppendEntriesResult.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RaftAlgorithm.Messages 3 | { 4 | public class AppendEntriesResponse : RaftMessageBase 5 | { 6 | public AppendEntriesResponse(int followerTerm, string followerId, bool success) 7 | { 8 | this.FollowerTerm = followerTerm; 9 | this.FollowerId = followerId; 10 | this.Succes = success; 11 | } 12 | public override string ToString() 13 | { 14 | return "OK"; 15 | } 16 | /// 17 | /// So leader can know who is message from 18 | /// 19 | /// 20 | public string FollowerId 21 | { 22 | get; 23 | private set; 24 | } 25 | public int FollowerTerm 26 | { 27 | get; 28 | private set; 29 | } 30 | /// 31 | /// true if follower contained entry matching prevLogIndex and prevLogTerm 32 | /// 33 | /// 34 | public bool Succes 35 | { 36 | get; 37 | private set; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /RaftDemo/Model/RaftClient.cs: -------------------------------------------------------------------------------- 1 | using RaftDemo.NodeSoftware; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NetworkModel; 8 | using NetworkModel.InProcNetwork; 9 | 10 | namespace RaftDemo.Model 11 | { 12 | public class RaftClient: NodeSoftwareBase 13 | { 14 | public RaftClient(INetworkModel networkModel, string clientId) : base(networkModel) 15 | { 16 | this.Id = clientId; 17 | Client = new NetworkClient(networkModel) { MaxConnectAttempts = -1 }; 18 | Client.ClientChannel.StateChanged += ClientChannel_StateChanged; 19 | } 20 | 21 | void ClientChannel_StateChanged(object sender, ConnectionState e) 22 | { 23 | 24 | } 25 | public NetworkClient Client 26 | { 27 | get; 28 | private set; 29 | } 30 | public string ServerAddress 31 | { 32 | get { return Client.RemoteAddress; } 33 | set { Client.RemoteAddress = value; } 34 | } 35 | 36 | protected override void OnMessageReceived(INetworkSocket channel, object message) 37 | { 38 | BroadcastExcept(message, channel); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /NetworkModel/INetworkModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel 8 | { 9 | public interface INetworkModel : IDisposable 10 | { 11 | /// 12 | /// Create network client 13 | /// 14 | /// Address of client, if null will be assigned by network 15 | /// 16 | INetworkSocket CreateClientSocket(string socketAddress = null); 17 | 18 | /// 19 | /// Create network server 20 | /// 21 | /// 22 | INetworkServer CreateServer(string socketAddress, bool startListening = true); 23 | 24 | /// 25 | /// Number of listening sockets in network model instance 26 | /// 27 | int ListeningSocketCount { get; } 28 | 29 | /// 30 | /// Number of connected sockets in network model instance 31 | /// 32 | int ConnectedSocketCount { get; } 33 | 34 | /// 35 | /// Exceptions thrown from other threads 36 | /// 37 | List Exceptions { get; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /RaftDemo/Converters/RaftStateToStyle.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows; 5 | using System.Windows.Data; 6 | 7 | namespace RaftDemo.Converters 8 | { 9 | public class RaftStateToStyle: IValueConverter 10 | { 11 | public Style FollowerStyle 12 | { 13 | get; 14 | set; 15 | } 16 | public Style LeaderStyle 17 | { 18 | get; 19 | set; 20 | } 21 | public Style CandidateStyle 22 | { 23 | get; 24 | set; 25 | } 26 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | if (!(value is RaftNodeState)) 29 | return null; 30 | 31 | RaftNodeState state = (RaftNodeState)value; 32 | 33 | if (state == RaftNodeState.Follower) 34 | return FollowerStyle; 35 | if (state == RaftNodeState.Leader) 36 | return LeaderStyle; 37 | if (state == RaftNodeState.Candidate) 38 | return CandidateStyle; 39 | return null; 40 | } 41 | 42 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 43 | { 44 | return null; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /CaliDiagram/Views/DiagramView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using CaliDiagram.ViewModels; 16 | 17 | namespace CaliDiagram.Views 18 | { 19 | /// 20 | /// Interaction logic for DiagramView.xaml 21 | /// 22 | public partial class DiagramView : UserControl 23 | { 24 | public DiagramView() 25 | { 26 | InitializeComponent(); 27 | diagram.PreviewMouseLeftButtonDown += diagram_PreviewMouseLeftButtonDown; 28 | diagram.MouseDown += diagram_MouseDown; 29 | } 30 | 31 | void diagram_MouseDown(object sender, MouseButtonEventArgs e) 32 | { 33 | var position = e.GetPosition(this); 34 | DiagramViewModel vm = DataContext as DiagramViewModel; 35 | 36 | } 37 | 38 | void diagram_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 39 | { 40 | if (e.ClickCount > 0) 41 | { 42 | //e.Handled = true; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /CaliDiagram/CaliDiagramHelpers.cs: -------------------------------------------------------------------------------- 1 | using Caliburn.Micro; 2 | using CaliDiagram.ViewModels; 3 | using CaliDiagram.Views; 4 | using System; 5 | using System.Windows; 6 | 7 | namespace CaliDiagram 8 | { 9 | public class CaliDiagramHelpers 10 | { 11 | public void InitViewLocator() 12 | { 13 | OriginalLocateForModel = ViewLocator.LocateForModel; 14 | ViewLocator.LocateForModel = LocateForModel; 15 | } 16 | private Func OriginalLocateForModel; 17 | 18 | private UIElement LocateForModel(object o, DependencyObject dependencyObject, object arg3) 19 | { 20 | if (o is NodeBaseViewModel) 21 | { 22 | Type type = o.GetType(); 23 | 24 | NodeBaseView diagramBaseView = new NodeBaseView(); 25 | 26 | if (type.IsSubclassOf(typeof(NodeBaseViewModel))) 27 | { 28 | UIElement element = OriginalLocateForModel(o, dependencyObject, arg3); 29 | FrameworkElement fe = element as FrameworkElement; 30 | 31 | diagramBaseView.Content = fe; 32 | ViewModelBinder.Bind(o, element, arg3); 33 | return diagramBaseView; 34 | } 35 | return diagramBaseView; 36 | } 37 | return OriginalLocateForModel(o, dependencyObject, arg3); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ActorTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ActorTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ActorTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("96c0e2ce-c94a-4dc1-81e7-1e595d29da7c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /NetworkTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("NetworkTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NetworkTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("bb757662-37d8-4c11-8c6d-bb0e5f137e22")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /NetworkModel/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("NetworkModel")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NetworkModel")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fc767fbb-0a07-4a4e-8eda-e3f2302bc08f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /RaftAlgorithm/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RaftAlgorithm")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RaftAlgorithm")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b473e866-7394-4d4a-a3f5-43560666ed3a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /RaftDemo/Converters/RaftStateToColorConverter.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | using System.Windows.Media; 6 | 7 | namespace RaftDemo.Converters 8 | { 9 | public class RaftStateToColorConverter:IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | if (!(value is RaftNodeState)) 14 | return null; 15 | 16 | RaftNodeState state = (RaftNodeState)value; 17 | if (parameter == null) 18 | { 19 | if (state == RaftNodeState.Follower) 20 | return Brushes.LightBlue; 21 | if (state == RaftNodeState.Leader) 22 | return Brushes.DarkRed; 23 | if (state == RaftNodeState.Candidate) 24 | return Brushes.Orange; 25 | } 26 | else 27 | { 28 | if (state == RaftNodeState.Follower) 29 | return Brushes.Black; 30 | if (state == RaftNodeState.Leader) 31 | return Brushes.White; 32 | if (state == RaftNodeState.Candidate) 33 | return Brushes.Black; 34 | } 35 | return Brushes.Black; 36 | } 37 | 38 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 39 | { 40 | return null; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /TaskSchedulerRun/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TaskSchedulerRun")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TaskSchedulerRun")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e0d2f213-7afd-442d-875d-45cd77db93d9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DiagramDesigner.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiagramDesignerExample", "DiagramDesigner\DiagramDesignerExample.csproj", "{1DF8B415-639F-40DF-B24D-8777C5B7C0EF}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiagramLib", "DiagramLib\DiagramLib.csproj", "{28019A1E-74D2-4481-8825-05961921DB7D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1DF8B415-639F-40DF-B24D-8777C5B7C0EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {1DF8B415-639F-40DF-B24D-8777C5B7C0EF}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {1DF8B415-639F-40DF-B24D-8777C5B7C0EF}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {1DF8B415-639F-40DF-B24D-8777C5B7C0EF}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {28019A1E-74D2-4481-8825-05961921DB7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {28019A1E-74D2-4481-8825-05961921DB7D}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {28019A1E-74D2-4481-8825-05961921DB7D}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {28019A1E-74D2-4481-8825-05961921DB7D}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/ServerToServerConnectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Timers; 2 | using System.Windows.Media; 3 | using System.Windows.Threading; 4 | using CaliDiagram.ViewModels; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using RaftDemo.Model; 10 | 11 | 12 | namespace RaftDemo.ViewModels 13 | { 14 | class ServerToServerConnectionViewModel: ConnectionViewModel 15 | { 16 | 17 | public ServerToServerConnectionViewModel(NodeBaseViewModel from, NodeBaseViewModel to, SimulationSettings worldSettings) : 18 | base(from, to) 19 | { 20 | this.worldSettings = worldSettings; 21 | StrokeThickness = 5; 22 | Stroke = Brushes.OrangeRed; 23 | // DispatcherTimer timer = new DispatcherTimer(); 24 | // timer.Interval = new TimeSpan(0,0,1); 25 | // timer.Tick += timer_Tick; 26 | // timer.Start(); 27 | Type = EdgeLineType.Bezier; 28 | } 29 | public override double Latency 30 | { 31 | get 32 | { 33 | return worldSettings.ServerToServerLatency; 34 | } 35 | } 36 | SimulationSettings worldSettings; 37 | private int n = 0; 38 | void timer_Tick(object sender, EventArgs e) 39 | { 40 | n++; 41 | if (n%2 == 0) 42 | { 43 | Stroke = Brushes.Red; 44 | } 45 | else 46 | { 47 | 48 | Stroke = Brushes.Orange; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NetworkModel/INetworkSocket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel 8 | { 9 | public interface INetworkSocket 10 | { 11 | /// 12 | /// Remote address which channel is connected to 13 | /// 14 | string RemoteAddress { get; } 15 | 16 | /// 17 | /// Local address 18 | /// 19 | string LocalAddress { get; } 20 | 21 | /// 22 | /// Fires when new message arrives from remote party 23 | /// 24 | event EventHandler MesageReceived; 25 | 26 | /// 27 | /// Fires when State changes 28 | /// 29 | event EventHandler StateChanged; 30 | 31 | /// 32 | /// Queue message to be sent to remote part 33 | /// 34 | /// 35 | /// false on failure 36 | bool SendMessage(object message); 37 | 38 | /// 39 | /// Request to close comm channel 40 | /// 41 | void Close(); 42 | 43 | /// 44 | /// Type of channel(client/server) 45 | /// 46 | ChannelType Type { get; } 47 | 48 | /// 49 | /// State of connection 50 | /// 51 | ConnectionState State { get; } 52 | 53 | void RequestConnectionTo(string remoteAddress); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /RaftDemo/Views/LogEntryView.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /NetworkModel/NetworkClientState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel 8 | { 9 | /// 10 | /// States for NetworkClient 11 | /// 12 | public enum NetworkClientState 13 | { 14 | /// 15 | /// Client is stopped(not connected nor trying to connect) 16 | /// 17 | Stopped, 18 | /// 19 | /// Invalid address was supplied to client 20 | /// 21 | InvalidAddress, 22 | /// 23 | /// Resolving address of remote server 24 | /// 25 | ResolvingName, 26 | /// 27 | /// Connecting to remote server 28 | /// 29 | Connecting, 30 | /// 31 | /// Connection is established 32 | /// 33 | Connected, 34 | /// 35 | /// Client is reconnecting(due to failed connection attempt or server side connection close) 36 | /// 37 | Reconnecting, 38 | /// 39 | /// Failed to connect 40 | /// 41 | ConnectFailed, 42 | /// 43 | /// Disconnecting 44 | /// 45 | Disconnecting, 46 | /// 47 | /// Connection was closed due to server decision/failure or data link failure 48 | /// Client might enter this state if MaxReconnectProbes is set to 1 49 | /// 50 | Disconnected 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /CaliDiagram/DefaultConnectionStrategy.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | using System.Diagnostics; 3 | using System.Windows; 4 | 5 | namespace CaliDiagram 6 | { 7 | /// 8 | /// Strategy that favourizes vertical connections(Top-bottom, bottom-top) 9 | /// It's best for wide rectangles nodes 10 | /// 11 | public class DefaultConnectionStrategy: IConnectorSideStrategy 12 | { 13 | public static AttachSides GetAttachmentSidesForConnection(Rect fromRect, Rect toRect) 14 | { 15 | double angle = DiagramHelpers.GetAngleBetweenRects(fromRect, toRect); 16 | 17 | if (angle > 320 || angle < 40) 18 | return new AttachSides(AttachDirection.Right, AttachDirection.Left); 19 | if (angle >= 40 && angle < 140) 20 | return new AttachSides(AttachDirection.Top, AttachDirection.Bottom); 21 | if (angle >= 140 && angle < 220) 22 | return new AttachSides(AttachDirection.Left, AttachDirection.Right); 23 | if (angle >= 220) 24 | return new AttachSides(AttachDirection.Bottom, AttachDirection.Top); 25 | 26 | return new AttachSides(AttachDirection.Top, AttachDirection.Top); 27 | } 28 | 29 | public AttachSides GetSidesForConnection(ConnectionViewModel connection) 30 | { 31 | Debug.Assert(connection.From != null, "From connection is null"); 32 | Debug.Assert(connection.To != null, "To connection is null"); 33 | Debug.Assert(!connection.From.Rect.IsEmpty, "From Rectangle is empty"); 34 | Debug.Assert(!connection.To.Rect.IsEmpty, "To Rectangle is empty"); 35 | return GetAttachmentSidesForConnection(connection.From.Rect, connection.To.Rect); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /CaliDiagram/Commands/AddConnectionCommand.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | using System; 3 | 4 | namespace CaliDiagram.Commands 5 | { 6 | class AddConnectionCommand: DiagramCommand 7 | { 8 | public AddConnectionCommand(DiagramViewModel diagram) 9 | : base(diagram) 10 | { 11 | Description = "Add connection"; 12 | } 13 | public override void OnSelected() 14 | { 15 | Diagram.HelpText = "Select start node for connection"; 16 | prevSelectedNode = null; 17 | } 18 | 19 | /// 20 | /// Most important random generator in whole sofrware 21 | /// 22 | Random rndStr = new Random(); 23 | 24 | string RandomNextStr 25 | { 26 | get 27 | { 28 | return nextOneStr[rndStr.Next(nextOneStr.Length)]; 29 | } 30 | } 31 | 32 | string[] nextOneStr = 33 | { 34 | "Want to add another one? Select start node again.", 35 | "Wow, you are getting better at this", 36 | "Another one?", 37 | "One more?", 38 | "Please select start node for connection", 39 | "More connections?", 40 | }; 41 | 42 | private NodeBaseViewModel prevSelectedNode = null; 43 | public override void HandleNodeClick(NodeBaseViewModel node) 44 | { 45 | if (prevSelectedNode != null) 46 | { 47 | Diagram.AddConnection(prevSelectedNode, node); 48 | prevSelectedNode = null; 49 | Diagram.HelpText = RandomNextStr; 50 | } 51 | else 52 | { 53 | Diagram.HelpText = "Great ! Now select destination"; 54 | prevSelectedNode = node; 55 | } 56 | 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /RaftAlgorithm/States/RaftStateBase.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm.Messages; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace RaftAlgorithm.States 9 | { 10 | public abstract class RaftStateBase 11 | { 12 | public RaftStateBase(RaftNode Node) 13 | { 14 | this.Node = Node; 15 | } 16 | protected RaftNode Node 17 | { 18 | get; 19 | private set; 20 | } 21 | public abstract RaftEventResult EnterState(); 22 | public virtual RaftEventResult OnTimeout() { return RaftEventResult.Empty; } 23 | 24 | public abstract RaftEventResult ReceiveRequestVote(RequestVote requestVote); 25 | public abstract RaftEventResult ReceiveRequestVoteResponse(RequestVoteResponse requestVoteResponse); 26 | public abstract RaftEventResult ReceiveAppendEntries(AppendEntriesRPC appendEntries); 27 | public abstract RaftEventResult ReceiveAppendEntriesResponse(AppendEntriesResponse appendEntriesResponse); 28 | 29 | 30 | protected RequestVoteResponse GrantVote 31 | { 32 | get 33 | { 34 | return new RequestVoteResponse() { VoteGranted = true, CurrentTerm = CurrentTerm, VoterId = Node.Id }; 35 | } 36 | } 37 | protected RequestVoteResponse DenyVote 38 | { 39 | get 40 | { 41 | return new RequestVoteResponse() { VoteGranted = false, CurrentTerm = CurrentTerm, VoterId = Node.Id }; 42 | } 43 | } 44 | 45 | protected int CurrentTerm 46 | { 47 | get { return Node.PersistedState.CurrentTerm; } 48 | set { Node.PersistedState.CurrentTerm = value; } 49 | } 50 | public abstract RaftNodeState State { get; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /RaftDemo/Views/Actors/ClientView.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | 17 | 18 | 19 | 20 | 21 | 33 | 34 | 35 | Disconnected 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /TaskSchedulerRun/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | using System.Threading; 9 | using NetworkModel.InProcNetwork; 10 | using System; 11 | using System.Linq; 12 | using System.Threading.Tasks; 13 | using Animatroller.Framework.Utility; 14 | 15 | namespace Animatroller.Framework.Utility 16 | { 17 | 18 | } 19 | namespace TaskSchedulerRun 20 | { 21 | class Program 22 | { 23 | static void Main(string[] args) 24 | { 25 | TestSchedulerRun run = new TestSchedulerRun(); 26 | run.Start(); 27 | } 28 | } 29 | 30 | class TestSchedulerRun 31 | { 32 | [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")] 33 | public static extern uint TimeBeginPeriod(uint uMilliseconds); 34 | 35 | 36 | 37 | 38 | HighPrecisionTimer swTimer = new HighPrecisionTimer(19); 39 | Stopwatch sw = new Stopwatch(); 40 | volatile int k = 0; 41 | void swTimer_Tick(object sender, HighPrecisionTimer.TickEventArgs e) 42 | { 43 | sw.Stop(); 44 | Console.WriteLine("time: " + sw.ElapsedMilliseconds); 45 | 46 | e.NextTickIn = 1 + k; 47 | k++; 48 | sw.Restart(); 49 | } 50 | 51 | public void Start() 52 | { 53 | new TsTest().TestSchedluler(); 54 | 55 | TimeBeginPeriod(1); 56 | // sw.Start(); 57 | // swTimer.Tick += swTimer_Tick; 58 | 59 | 60 | // Thread.Sleep(10000); 61 | Console.ReadKey(); 62 | } 63 | 64 | void HandleAndFireNextTask() 65 | { 66 | Console.WriteLine("xxx"); 67 | // ts.SchedluleTask(()=>HandleAndFireNextTask(), TimeSpan.FromMilliseconds(500)); 68 | } 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /RaftAlgorithm/Messages/AppendEntriesRPC.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Collections.Generic; 3 | 4 | namespace RaftAlgorithm.Messages 5 | { 6 | public class AppendEntriesRPC : RaftMessageBase 7 | { 8 | public AppendEntriesRPC(int leaderTerm, string leaderId) 9 | { 10 | this.LeaderId = leaderId; 11 | this.LeaderTerm = leaderTerm; 12 | } 13 | public override string ToString() 14 | { 15 | return "AE"; 16 | } 17 | 18 | /// 19 | /// Leader term number 20 | /// 21 | /// 22 | public int LeaderTerm 23 | { 24 | get; 25 | set; 26 | } 27 | 28 | /// 29 | /// Id of leader 30 | /// 31 | /// 32 | public string LeaderId 33 | { 34 | get; 35 | set; 36 | } 37 | /// 38 | /// Index of log entry immedietaly proceeding new ones 39 | /// 40 | /// 41 | public int PrevLogIndex 42 | { 43 | get; 44 | set; 45 | } 46 | 47 | /// 48 | /// Index of prevLogIndex log entry 49 | /// 50 | /// 51 | public int PrevLogTerm 52 | { 53 | get; 54 | set; 55 | } 56 | /// 57 | /// Log entries to store(may be null) 58 | /// 59 | /// 60 | public List> LogEntries 61 | { 62 | get; 63 | set; 64 | } 65 | 66 | /// 67 | /// Leader commit index 68 | /// 69 | public long LeaderCommit 70 | { 71 | get; 72 | set; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Raft Consensus Visualization & CaliDiagram 2 | 3 | ######This repository was supposed to be be only for CaliDiagram library but it slowly evelves into visualization of any actor system. Current goal is to provide solution that would help developing and visualizing new distributed algorithms more easily. 4 | 5 | *** 6 | #####Projects incuded in solution: 7 | * CaliDiagram - library for WPF diagramming that uses ViewModel-First approach, 8 | * NetworkModel - framework for messaging, now InProc network simulation only, 9 | * RaftAlgorithm - Buggy and incomplete implementation of Raft Consensus algorithm, 10 | * RaftDemo - WPF application for visualizing raft algorithm, needs to be separated into two projects. 11 | 12 | #####What needs to be done: 13 | * Improve network model so it could emulate tcp/ip like messaging correctly, 14 | * Figure out basic elements of actor system(ClientActor, ServerActor,etc), 15 | * Wire up network model to GUI for connection/socket/packet visualization, 16 | * Separate RaftVisualization as an example use of code from this repo, 17 | * Finally, make it possible to wire netowrk model to any existing messaging library, possibly NetMQ. 18 | * Decide whether to rename/split CaliDiagram into several github repositories 19 | 20 | #####CaliDiagram features: 21 | * Creating your own diagram nodes using ViewModel first approach 22 | * Customizing connections between nodes 23 | * Bezier/straight connection line 24 | * Customizing attach descriptors 25 | * Saving and loading to XML 26 | 27 | #####Some progress: 28 | ![raft2](https://cloud.githubusercontent.com/assets/3065454/7144999/7ec540f0-e2e9-11e4-9346-f0d540c409b5.png) 29 | 30 | 31 | ![sample diagram](http://95.85.14.120/dwn/cali.png) 32 | 33 | 34 | ![sample diagram](https://cloud.githubusercontent.com/assets/3065454/5565103/b83c2e1e-8ee5-11e4-803a-992050d5fa0c.png) 35 | 36 | ![calidiagram view-model first](https://cloud.githubusercontent.com/assets/3065454/5696991/2711f360-99e4-11e4-808a-8a221aafcfd6.png) 37 | -------------------------------------------------------------------------------- /NetworkModel/INetworkServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel 8 | { 9 | public class MessageReceivedArgs 10 | { 11 | public MessageReceivedArgs(INetworkSocket socket, object message) 12 | { 13 | this.Socket = socket; 14 | this.Message = message; 15 | } 16 | public object Message { get; private set;} 17 | public INetworkSocket Socket {get; private set;} 18 | } 19 | public interface INetworkServer: IDisposable 20 | { 21 | /// 22 | /// Start accepting connections 23 | /// 24 | /// 25 | /// 26 | bool StartListening(string address); 27 | 28 | /// 29 | /// Stop listening in current address 30 | /// 31 | /// 32 | bool Stop(); 33 | 34 | /// 35 | /// Listening address 36 | /// 37 | string Address { get; } 38 | 39 | /// 40 | /// List of all client channels 41 | /// 42 | IList ClientChannels { get; } 43 | 44 | /// 45 | /// Listening channel 46 | /// 47 | INetworkSocket ListeningChannel { get; } 48 | /// 49 | /// New client connected to server 50 | /// 51 | event EventHandler ClientConnected; 52 | /// 53 | /// Connection to server was closed 54 | /// 55 | event EventHandler ClientDisconnected; 56 | 57 | /// 58 | /// Fired when message from any client is received 59 | /// 60 | event EventHandler MessageReceived; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/LogEntryViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Media; 8 | using Caliburn.Micro; 9 | using RaftAlgorithm; 10 | 11 | namespace RaftDemo.ViewModels 12 | { 13 | public class LogEntryViewModel : PropertyChangedBase 14 | { 15 | public LogEntryViewModel(LogEntry entry) 16 | { 17 | this.Entry = entry; 18 | } 19 | public LogEntry Entry 20 | { 21 | get; 22 | private set; 23 | } 24 | private Thickness _CellMargin; 25 | public Thickness CellMargin 26 | { 27 | get { return _CellMargin; } 28 | set 29 | { 30 | if (_CellMargin != value) 31 | { 32 | _CellMargin = value; 33 | NotifyOfPropertyChange(() => CellMargin); 34 | } 35 | } 36 | } 37 | 38 | private Brush _EntryColor; 39 | public Brush EntryColor 40 | { 41 | get { return _EntryColor; } 42 | set 43 | { 44 | if (_EntryColor != value) 45 | { 46 | _EntryColor = value; 47 | NotifyOfPropertyChange(() => EntryColor); 48 | } 49 | } 50 | } 51 | 52 | public int CommitIndex 53 | { 54 | get 55 | { 56 | return Entry.CommitIndex; 57 | } 58 | } 59 | public int Term 60 | { 61 | get 62 | { 63 | return Entry.Term; 64 | } 65 | } 66 | public string Data 67 | { 68 | get 69 | { 70 | if (Entry.Data == null) 71 | return "[null]"; 72 | return Entry.Data.ToString(); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /RaftDemo/Views/Actors/ServerView.xaml.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm; 2 | using RaftDemo.Model; 3 | using RaftDemo.ViewModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows; 10 | using System.Windows.Controls; 11 | using System.Windows.Data; 12 | using System.Windows.Documents; 13 | using System.Windows.Input; 14 | using System.Windows.Media; 15 | using System.Windows.Media.Animation; 16 | using System.Windows.Media.Imaging; 17 | using System.Windows.Navigation; 18 | using System.Windows.Shapes; 19 | using RaftDemo.ViewModels.Actors; 20 | 21 | namespace RaftDemo.Views.Actors 22 | { 23 | /// 24 | /// Interaction logic for DiagramNodeBigView.xaml 25 | /// 26 | public partial class ServerView : UserControl 27 | { 28 | public ServerView() 29 | { 30 | InitializeComponent(); 31 | DataContextChanged += DiagramNodeBigView_DataContextChanged; 32 | } 33 | 34 | 35 | 36 | void DiagramNodeBigView_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 37 | { 38 | var vm = DataContext as ServerViewModel ; 39 | if (vm != null) 40 | { 41 | RaftHost raftNode = vm.NodeSoftware as RaftHost; 42 | raftNode.OnRaftEvent += raftNode_OnRaftEvent; 43 | } 44 | } 45 | 46 | void raftNode_OnRaftEvent(object sender, RaftEventResult e) 47 | { 48 | if(e.TimerSet) 49 | Dispatcher.BeginInvoke(new Action(()=>StartTimerAnimation(e.TimerValue))); 50 | } 51 | 52 | void StartTimerAnimation(int ms) 53 | { 54 | Storyboard sb = this.FindResource("timerStoryboard") as Storyboard; 55 | DoubleAnimation anim = (DoubleAnimation)sb.Children.FirstOrDefault(c => c.Name == "doubleAnimation"); 56 | anim.Duration = TimeSpan.FromMilliseconds(ms); 57 | sb.Begin(); 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/Actors/ClientViewModel.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | using RaftDemo.Model; 3 | using RaftDemo.NodeSoftware; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using PropertyChanged; 10 | using NetworkModel; 11 | 12 | namespace RaftDemo.ViewModels.Actors 13 | { 14 | [ImplementPropertyChanged] 15 | public class ClientViewModel : ActorViewModel 16 | { 17 | RaftClient raftClient; 18 | public ClientViewModel(RaftClient raftClient) 19 | : base(raftClient) 20 | { 21 | Name = raftClient.Id; 22 | State = "Established"; 23 | this.raftClient = raftClient; 24 | this.raftClient.Client.StateChanged += Client_StateChanged; 25 | ClientStateToView(); 26 | } 27 | 28 | void Client_StateChanged(object sender, NetworkClientState e) 29 | { 30 | ClientStateToView(); 31 | } 32 | 33 | 34 | void ClientStateToView() 35 | { 36 | NetworkClientState state = raftClient.Client.State; 37 | State = state.ToString(); 38 | if (raftClient.Client.IsStarted) 39 | ButtonText = "Stop"; 40 | else 41 | ButtonText = "Start"; 42 | } 43 | public string State 44 | { 45 | get; 46 | set; 47 | } 48 | public string Address 49 | { 50 | get 51 | { 52 | return raftClient.Client.ClientChannel.LocalAddress; 53 | } 54 | } 55 | public string RemoteAddress 56 | { 57 | get { return raftClient.ServerAddress; } 58 | set { raftClient.ServerAddress = value;} 59 | } 60 | public string ButtonText 61 | { 62 | get; 63 | set; 64 | } 65 | public void StartStop() 66 | { 67 | raftClient.Client.IsStarted = !raftClient.Client.IsStarted; 68 | ClientStateToView(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /RaftDemo.Tests/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | RaftDemo.Tests 10 | Tom 11 | Images\UnitTestStoreLogo.png 12 | RaftDemo.Tests 13 | 14 | 15 | 16 | 6.3.0 17 | 6.3.0 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 35 | 36 | 37 | 38 | 39 | 42 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /RaftDemo/Resources/WindowsIcons-license.txt: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Please carefully understand the license and download the latest icons at ModernUIIcons.com. 4 | 5 | ## Understand Your Rights 6 | No Attribution and No Derived Works 7 | http://creativecommons.org/licenses/by-nd/3.0/ * 8 | 9 | - If your project is open source include this license file in the source. 10 | - Nothing is needed in the front facing project (UNLESS you 11 | are using any of the icons listed below in the attribution section). 12 | - Commercial use is not only allowed but encouraged. If it is an icon 13 | in the attribution list below, you still need to attribute those! 14 | - Do not distribute the entire package (I've allowed this dozens of 15 | times for open source projects, but email me first). 16 | 17 | ## Creator 18 | - Austin Andrews (@templarian) 19 | 20 | ## Contributor** 21 | - Jay Zawrotny (@JayZawrotny) 22 | - A Bunch 23 | - Oren Nachman 24 | - appbar.chevron.down 25 | - appbar.chevron.up 26 | - appbar.chevron.left 27 | - appbar.chevron.right 28 | 29 | ## Derived Works 30 | - Alex Peattie 31 | - Social: http://www.alexpeattie.com/projects/justvector_icons/ 32 | 33 | ## Attribution*** 34 | - Kris Vandermotten (@kvandermotten) 35 | - appbar.medical.pulse 36 | - Constantin Kichinsky (@kichinsky) 37 | - appbar.currency.rubles 38 | - appbar.currency.grivna 39 | - Massimo Savazzi (@msavazzi) 40 | - List of missing exported icons 41 | - Proletkult Graphik, from The Noun Project 42 | - appbar.draw.pen (inspired) 43 | - Olivier Guin, from The Noun Project 44 | - appbar.draw.marker 45 | - Gibran Bisio, from The Noun Project 46 | - appbar.draw.bucket 47 | Andrew Forrester, from The Noun Project 48 | - appbar.fingerprint 49 | 50 | * The license is for attribution, but this is not required. 51 | ** Developers and designers that emailed Templarian the source .design icons to be added into the package. PNGs also accepted, but may take longer to be added. 52 | *** Icons I've copied so closely you want to attribute them and are also under the CC license. 53 | 54 | Contact 55 | - http://templarian.com/ 56 | - admin[@]templarian[.]com 57 | 58 | * Does not apply to copyrighted logos 59 | - Skype 60 | - Facebook 61 | - Twitter 62 | - etc... 63 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ServerActor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.Actors 8 | { 9 | /// 10 | /// Server actor listens on given address and also can request connections to other actors 11 | /// 12 | public class ServerActor: ActorBase 13 | { 14 | public INetworkServer Server { get; private set; } 15 | public ServerActor(INetworkModel networkModel, string address):base(networkModel) 16 | { 17 | Address = address; 18 | Server = networkModel.CreateServer(address, false); 19 | Server.MessageReceived += Server_MessageReceived; 20 | Server.ClientConnected += Server_ClientConnected; 21 | Server.ClientDisconnected += Server_ClientDisconnected; 22 | } 23 | /// 24 | /// Listening address 25 | /// 26 | public string Address { get; private set; } 27 | public override void Start() 28 | { 29 | base.Start(); 30 | Server.StartListening(Address); 31 | } 32 | 33 | public override void Stop() 34 | { 35 | base.Stop(); 36 | Server.Stop(); 37 | } 38 | 39 | Dictionary ServerSocketToChannel = new Dictionary(); 40 | 41 | void Server_ClientDisconnected(object sender, INetworkSocket e) 42 | { 43 | 44 | var channel = ServerSocketToChannel[e]; 45 | 46 | RaiseChannelRemoved(channel); 47 | } 48 | 49 | void Server_ClientConnected(object sender, INetworkSocket e) 50 | { 51 | ActorChannel actorChannel = new ActorChannel(e); 52 | ServerSocketToChannel.Add(e, actorChannel); 53 | RaiseChannelAdded(actorChannel); 54 | } 55 | 56 | void Server_MessageReceived(object sender, MessageReceivedArgs e) 57 | { 58 | var channel = ServerSocketToChannel[e.Socket]; 59 | RaiseMessageReceived(channel, e.Message); 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /NetworkModel/InProcNetwork/SocketId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.InProcNetwork 8 | { 9 | /// 10 | /// SocketId is tuple [local_address, remote_address] 11 | /// 12 | class SocketId: IEquatable 13 | { 14 | /// 15 | /// Get socket id of socket [local_address, remote_address] 16 | /// 17 | /// 18 | /// 19 | public static SocketId FromSocket(InProcSocket socket) 20 | { 21 | return new SocketId(socket.LocalAddress, socket.RemoteAddress); 22 | } 23 | /// 24 | /// Get id of associated remote socket [remote_address, local_address] 25 | /// 26 | /// 27 | /// 28 | public static SocketId RemoteSocketId(InProcSocket socket) 29 | { 30 | return new SocketId(socket.RemoteAddress, socket.LocalAddress); 31 | } 32 | public SocketId(string localAddress, string remoteAddress) 33 | { 34 | if (string.IsNullOrEmpty(localAddress) || string.IsNullOrEmpty(remoteAddress)) 35 | throw new ArgumentException("Empty address passed to SocketId constructor"); 36 | this.LocalAddress = localAddress; 37 | this.RemoteAddress = remoteAddress; 38 | } 39 | public string LocalAddress { get; private set; } 40 | public string RemoteAddress { get; private set; } 41 | public override bool Equals(object obj) 42 | { 43 | var other = obj as SocketId; 44 | return Equals(other); 45 | } 46 | public override string ToString() 47 | { 48 | return string.Format("{0} => {1}", LocalAddress, RemoteAddress); 49 | } 50 | 51 | public bool Equals(SocketId other) 52 | { 53 | if (other == null) 54 | return false; 55 | return other.LocalAddress == LocalAddress && other.RemoteAddress == RemoteAddress; 56 | } 57 | public override int GetHashCode() 58 | { 59 | return LocalAddress.GetHashCode() ^ RemoteAddress.GetHashCode(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /CaliDiagram/Serialization/XmlSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.Serialization; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using System.Xml; 10 | 11 | namespace CaliDiagram.Serialization 12 | { 13 | /// 14 | /// Using data contract serializer to load or save object tree into xml files 15 | /// 16 | /// 17 | public class XmlSettings where T: new() 18 | { 19 | DataContractSerializer serializer; 20 | public XmlSettings(IEnumerable knownTypes) 21 | { 22 | serializer = new DataContractSerializer(typeof(T), knownTypes, 23 | 0x7FFF /*maxItemsInObjectGraph*/, 24 | false /*ignoreExtensionDataObject*/, 25 | true /*preserveObjectReferences : this is where the magic happens */, 26 | null /*dataContractSurrogate*/); 27 | } 28 | public T ModelFromSettings(string filename) 29 | { 30 | try 31 | { 32 | if (!File.Exists(filename)) 33 | return new T(); 34 | using (FileStream fs = File.Open(filename, FileMode.Open)) 35 | { 36 | T model = (T)serializer.ReadObject(fs); 37 | // model.SettingsFilename = filename; 38 | return model; 39 | } 40 | 41 | } 42 | catch (Exception ex) 43 | { 44 | MessageBox.Show("Failed to load settings from " + filename + " !: " + ex.ToString()); 45 | //MessageBox.Show("Failed to load settings from " + filename + " !: " + ex.InnerException.Message); 46 | return new T(); 47 | } 48 | } 49 | 50 | public void SaveModel(T appModel, string filename) 51 | { 52 | try 53 | { 54 | var settings = new XmlWriterSettings { Indent = true }; 55 | 56 | using (var w = XmlWriter.Create(filename, settings)) 57 | serializer.WriteObject(w, appModel); 58 | } 59 | catch (Exception ex) 60 | { 61 | 62 | MessageBox.Show("Failed to save settings to !: " + ex.ToString()); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /RaftDemo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("DiagramDesigner")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("DiagramDesigner")] 15 | [assembly: AssemblyCopyright("Copyright © 2014")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /CaliDiagram/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("CaliDiagram")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("CaliDiagram")] 15 | [assembly: AssemblyCopyright("Copyright © Tomasz Ścisłowicz 2015" )] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly:ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /TaskSchedulerRun/TsTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using NetworkModel.InProcNetwork.TaskScheduling; 8 | 9 | namespace TaskSchedulerRun 10 | { 11 | class TsTest 12 | { 13 | class TimingTestTask 14 | { 15 | public int Id { get; set; } 16 | public int ExpectedDelay { get; set; } 17 | public int ActualDelay { get; set; } 18 | public volatile int WasExecuted = 0; 19 | 20 | Stopwatch sw = new Stopwatch(); 21 | public void StartCounting() 22 | { 23 | sw.Start(); 24 | } 25 | public void Executed() 26 | { 27 | Interlocked.Increment(ref WasExecuted); 28 | ActualDelay = Convert.ToInt32(sw.ElapsedMilliseconds); 29 | sw.Stop(); 30 | } 31 | } 32 | 33 | public void TestSchedluler() 34 | { 35 | List taskTimings = new List(); 36 | 37 | 38 | for(int i=0; i < 1000; i++) 39 | { 40 | taskTimings.Add(i + 5); 41 | taskTimings.Add(i /2 + 100); 42 | } 43 | 44 | TaskScheduler ts = new TaskScheduler(); 45 | 46 | List testTasks = new List(); 47 | // create tasks 48 | for (int i = 0; i < taskTimings.Count; i++) 49 | { 50 | TimingTestTask task = new TimingTestTask() { ExpectedDelay = taskTimings[i], Id = i }; 51 | testTasks.Add(task); 52 | 53 | } 54 | int executedTasks = 0; 55 | 56 | foreach (var task in testTasks) 57 | { 58 | task.StartCounting(); 59 | ts.SchedluleTask(() => { task.Executed(); Interlocked.Increment(ref executedTasks); }, TimeSpan.FromMilliseconds(task.ExpectedDelay)); 60 | } 61 | 62 | 63 | Thread.Sleep(11000); 64 | Thread.MemoryBarrier(); 65 | decimal meanAbsoluteError = 0; 66 | foreach (var task in testTasks) 67 | { 68 | if (task.WasExecuted != 1) 69 | Console.WriteLine("Task {0} was not executed !", task.Id); 70 | 71 | meanAbsoluteError += Math.Abs(task.ActualDelay - task.ExpectedDelay); 72 | 73 | Console.WriteLine("Exptected: {0}\tActual: {1}", task.ExpectedDelay, task.ActualDelay); 74 | } 75 | meanAbsoluteError /= testTasks.Count; 76 | Console.WriteLine("Total: {0}\tExecuted: {1}", testTasks.Count, executedTasks); 77 | Console.WriteLine("MAE: {0}", meanAbsoluteError); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /RaftDemo/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.0 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RaftDemo.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RaftDemo.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /CaliDiagram/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.0 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CaliDiagram.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CaliDiagram.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /RaftDemo/NodeSoftware/TimeoutTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Timers; 7 | using System.Windows; 8 | 9 | namespace RaftDemo.NodeSoftware 10 | { 11 | public class TimeoutTimer: IDisposable 12 | { 13 | NodeSoftwareBase software; 14 | public TimeoutTimer(NodeSoftwareBase software) 15 | { 16 | this.software = software; 17 | isDisposed = false; 18 | timer = new Timer(); 19 | } 20 | Timer timer; 21 | 22 | /// 23 | /// Timer not started - actiong will be executed on T+ms 24 | /// Timer started - stop previous timer - actiong will be executed on T+ms 25 | /// 26 | void SetTimeout(int ms) 27 | { 28 | timer.Stop(); 29 | if (ms == 0) 30 | ms = 1; 31 | timer.Interval = ms; 32 | timer.Elapsed -= timer_Elapsed; 33 | timer.Elapsed += timer_Elapsed; 34 | if (!software.IsStarted) 35 | return; 36 | timer.Start(); 37 | if (Application.Current == null) 38 | return; 39 | // update gui 40 | Application.Current.Dispatcher.BeginInvoke(new Action(() => 41 | { 42 | if (Application.Current == null) 43 | return; 44 | if (TimerSet != null) 45 | TimerSet(this, ms); 46 | })); 47 | 48 | } 49 | static Random rnd = new Random(); 50 | 51 | /// 52 | /// Sets time to timeout in random time between T+msFrom and T+msTo 53 | /// 54 | /// Milliseconds from 55 | /// Milliseconds to 56 | public void SetRandomTimeout(int msFrom, int msTo) 57 | { 58 | double factor = 1; 59 | msFrom = Convert.ToInt32( factor * msFrom); 60 | msTo = Convert.ToInt32( factor * msTo); 61 | 62 | if (msFrom > msTo) 63 | throw new ArgumentException("Invalid timer range"); 64 | int randomPart = rnd.Next(msTo - msFrom); 65 | int timeout = msFrom + randomPart; 66 | SetTimeout(timeout); 67 | } 68 | 69 | void timer_Elapsed(object sender, ElapsedEventArgs e) 70 | { 71 | if (Application.Current == null) 72 | return; 73 | if (isDisposed) 74 | return; 75 | timer.Stop(); 76 | software.InputQueue.Add(this); 77 | if (Elapsed != null) 78 | Elapsed(this, EventArgs.Empty); 79 | } 80 | public event EventHandler TimerSet; 81 | public event EventHandler Elapsed; 82 | 83 | 84 | bool isDisposed = false; 85 | public void Dispose() 86 | { 87 | isDisposed = true; 88 | timer.Dispose(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /TaskSchedulerRun/TaskSchedulerRun.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F7117825-CEBA-406F-A36D-5AC6EC8B21C8} 8 | Exe 9 | Properties 10 | TaskSchedulerRun 11 | TaskSchedulerRun 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | {44ca1876-b5be-4438-a0dd-bb3a7b6eed5f} 56 | NetworkModel 57 | 58 | 59 | 60 | 67 | -------------------------------------------------------------------------------- /RaftDemo/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 42 | 46 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /RaftDemo/AppBootstrapper.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram; 2 | using CaliDiagram.ViewModels; 3 | using System.Reflection; 4 | 5 | namespace RaftDemo 6 | { 7 | using Caliburn.Metro; 8 | using Caliburn.Micro; 9 | using RaftDemo.ViewModels; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Diagnostics; 13 | using System.Net.Http; 14 | using System.Threading.Tasks; 15 | 16 | class TextListener : TraceListener 17 | { 18 | 19 | public override void Write(string message) 20 | { 21 | Console.Write(message); 22 | } 23 | 24 | public override void WriteLine(string message) 25 | { 26 | Console.WriteLine(message); 27 | } 28 | } 29 | public class AppBootstrapper : CaliburnMetroCompositionBootstrapper 30 | { 31 | private SimpleContainer container; 32 | 33 | public AppBootstrapper() 34 | { 35 | EnableTrace(); 36 | Initialize(); 37 | } 38 | void EnableTrace() 39 | { 40 | Trace.Listeners.Add(new TextListener()); 41 | Trace.AutoFlush = true; 42 | Trace.Indent(); 43 | } 44 | protected override IEnumerable SelectAssemblies() 45 | { 46 | Assembly diagramAssembly = typeof (DiagramViewModel).Assembly; 47 | Assembly thisAssembly = Assembly.GetExecutingAssembly(); 48 | return new Assembly[] 49 | { 50 | thisAssembly, 51 | diagramAssembly 52 | }; 53 | } 54 | 55 | 56 | protected override void Configure() 57 | { 58 | container = new SimpleContainer(); 59 | 60 | container.Singleton(); 61 | container.Singleton(); 62 | container.PerRequest(); 63 | 64 | var diagramHelpers = new CaliDiagramHelpers(); 65 | diagramHelpers.InitViewLocator(); 66 | } 67 | 68 | protected override object GetInstance(Type service, string key) 69 | { 70 | var instance = container.GetInstance(service, key); 71 | if (instance != null) 72 | return instance; 73 | throw new InvalidOperationException("Could not locate any instances."); 74 | } 75 | 76 | protected override IEnumerable GetAllInstances(Type service) 77 | { 78 | return container.GetAllInstances(service); 79 | } 80 | 81 | protected override void BuildUp(object instance) 82 | { 83 | container.BuildUp(instance); 84 | } 85 | 86 | protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) 87 | { 88 | DisplayRootViewFor(); 89 | } 90 | protected override void OnExit(object sender, EventArgs e) 91 | { 92 | var shell = container.GetAllInstances(); 93 | foreach (var s in shell) 94 | s.Close(); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /CaliDiagram/ViewModels/AttachPoint.cs: -------------------------------------------------------------------------------- 1 | using Caliburn.Micro; 2 | using System.Windows; 3 | 4 | namespace CaliDiagram.ViewModels 5 | { 6 | public enum AttachDirection 7 | { 8 | Top = 0, 9 | Right = 1, 10 | Bottom = 2, 11 | Left = 3, 12 | Center, 13 | Float 14 | }; 15 | 16 | public delegate void AttachPointLocationChangedDelegate(AttachPoint ap, Point location); 17 | 18 | public delegate void AttachPointDirectionChangedDelegate(AttachPoint ap, AttachDirection direction); 19 | 20 | public class AttachPoint : PropertyChangedBase 21 | { 22 | public AttachPoint(AttachDirection direction, ConnectionViewModel connection, NodeBaseViewModel associatedControl) 23 | { 24 | Side = direction; 25 | this.Connection = connection; 26 | this.Control = associatedControl; 27 | } 28 | /// 29 | /// Control associated with this attach point 30 | /// 31 | public NodeBaseViewModel Control { get; private set; } 32 | 33 | /// 34 | /// Width if control 35 | /// 36 | public double Width 37 | { 38 | get 39 | { 40 | if(Control == null) 41 | return 0; 42 | return Control.Size.Width; 43 | } 44 | } 45 | /// 46 | /// Height of control 47 | /// 48 | public double Height 49 | { 50 | get 51 | { 52 | if(Control == null) 53 | return 0; 54 | return Control.Size.Height; 55 | } 56 | } 57 | public ConnectionViewModel Connection 58 | { 59 | get; 60 | private set; 61 | } 62 | private AttachDirection _direction; 63 | public AttachDirection Side 64 | { 65 | get { return _direction; } 66 | set 67 | { 68 | if (_direction != value) 69 | { 70 | if (DirectionChanging != null) 71 | DirectionChanging(this, value); 72 | 73 | _direction = value; 74 | 75 | } 76 | } 77 | } 78 | public int Order { get; set; } 79 | 80 | 81 | 82 | public event AttachPointLocationChangedDelegate LocationChanged; 83 | public event AttachPointDirectionChangedDelegate DirectionChanging; 84 | 85 | private Point _Location; 86 | public Point Location 87 | { 88 | get { return _Location; } 89 | set 90 | { 91 | if (_Location != value) 92 | { 93 | _Location = value; 94 | if (LocationChanged != null) 95 | LocationChanged(this, Location); 96 | NotifyOfPropertyChange(()=>Location); 97 | } 98 | } 99 | } 100 | 101 | public Point ControlLocation { get; set; } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /NetworkTest/SchedlulerTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Threading; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using NetworkModel.InProcNetwork; 7 | using NetworkModel.InProcNetwork.TaskScheduling; 8 | using NFluent; 9 | 10 | 11 | namespace NetworkTest 12 | { 13 | [TestClass] 14 | public class SchedlulerTest 15 | { 16 | class TimingTestTask 17 | { 18 | public int Id { get; set; } 19 | public int ExpectedDelay { get; set; } 20 | public int ActualDelay { get; set; } 21 | public bool WasExecuted { get; private set; } 22 | 23 | Stopwatch sw = new Stopwatch(); 24 | public void StartCounting() 25 | { 26 | sw.Start(); 27 | } 28 | public void Executed() 29 | { 30 | WasExecuted = true; 31 | ActualDelay = Convert.ToInt32(sw.ElapsedMilliseconds); 32 | sw.Stop(); 33 | } 34 | } 35 | [TestMethod] 36 | public void TestSchedluler() 37 | { 38 | List taskTimings = new List(); 39 | taskTimings.Add(400); 40 | taskTimings.Add(54); 41 | taskTimings.Add(774); 42 | taskTimings.Add(400); 43 | taskTimings.Add(54); 44 | taskTimings.Add(774); 45 | taskTimings.Add(400); 46 | taskTimings.Add(54); 47 | taskTimings.Add(774); 48 | taskTimings.Add(400); 49 | taskTimings.Add(54); 50 | taskTimings.Add(774); 51 | taskTimings.Add(400); 52 | taskTimings.Add(54); 53 | taskTimings.Add(774); 54 | taskTimings.Add(400); 55 | taskTimings.Add(54); 56 | taskTimings.Add(774); 57 | taskTimings.Add(400); 58 | taskTimings.Add(54); 59 | taskTimings.Add(774); 60 | taskTimings.Add(400); 61 | taskTimings.Add(54); 62 | taskTimings.Add(774); 63 | 64 | TaskScheduler ts = new TaskScheduler(); 65 | 66 | List testTasks = new List(); 67 | // create tasks 68 | for (int i = 0; i < taskTimings.Count; i++ ) 69 | { 70 | TimingTestTask task = new TimingTestTask() { ExpectedDelay = taskTimings[i], Id = i }; 71 | testTasks.Add(task); 72 | if (i % 11 == 0) 73 | Thread.Sleep(1000); 74 | } 75 | 76 | foreach(var task in testTasks) 77 | { 78 | task.StartCounting(); 79 | ts.SchedluleTask(task.Executed, TimeSpan.FromMilliseconds(task.ExpectedDelay)); 80 | } 81 | 82 | 83 | Thread.Sleep(5000); 84 | 85 | decimal meanAbsoluteError = 0; 86 | foreach(var task in testTasks) 87 | { 88 | Check.That(task.WasExecuted); 89 | meanAbsoluteError += Math.Abs(task.ActualDelay - task.ExpectedDelay); 90 | } 91 | meanAbsoluteError /= testTasks.Count; 92 | Check.That(meanAbsoluteError).IsLessThan(10); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /RaftDemo/Model/SimulationSettings.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace RaftDemo.Model 9 | { 10 | public class SimulationSettings: IRaftNodeSettings 11 | { 12 | public SimulationSettings() 13 | { 14 | SoundEnabled = false; 15 | WorldSpeedFactor = 0.1; 16 | ServerToServerLatencySetting = 33; 17 | ClientToServerLatencySetting = 40; 18 | 19 | LeaderTimeoutFromSetting = 70; 20 | LeaderTimeoutToSetting = 70; 21 | 22 | FollowerTimeoutFromSetting = 150; 23 | FollowerTimeoutToSetting = 300; 24 | 25 | ClusterSize = 4; 26 | PacketVisualizationEnabled = true; 27 | 28 | } 29 | public bool PacketVisualizationEnabled 30 | { 31 | get; 32 | set; 33 | } 34 | double ApplySpeedFactor(double value) 35 | { 36 | return value * (1.0 / WorldSpeedFactor); 37 | } 38 | public bool SoundEnabled 39 | { 40 | get; 41 | set; 42 | } 43 | 44 | public double ServerToServerLatencySetting 45 | { 46 | get; 47 | set; 48 | } 49 | public double ClientToServerLatencySetting 50 | { 51 | get; 52 | set; 53 | } 54 | 55 | public double ServerToServerLatency 56 | { 57 | get 58 | { 59 | return ApplySpeedFactor(ServerToServerLatencySetting); 60 | } 61 | } 62 | public double ClientToServerLatency 63 | { 64 | get 65 | { 66 | return ApplySpeedFactor(ClientToServerLatencySetting); 67 | } 68 | } 69 | public double WorldSpeedFactor 70 | { 71 | get; 72 | set; 73 | } 74 | 75 | public int ClusterSize 76 | { 77 | get; 78 | set; 79 | } 80 | 81 | public int LeaderTimeoutFromSetting 82 | { 83 | get; 84 | set; 85 | } 86 | 87 | public int LeaderTimeoutToSetting 88 | { 89 | get; 90 | set; 91 | } 92 | 93 | public int FollowerTimeoutFromSetting 94 | { 95 | get; 96 | set; 97 | } 98 | 99 | public int FollowerTimeoutToSetting 100 | { 101 | get; 102 | set; 103 | } 104 | 105 | 106 | public int LeaderTimeoutFrom 107 | { 108 | get { return Convert.ToInt32(ApplySpeedFactor(LeaderTimeoutFromSetting)); } 109 | } 110 | 111 | public int LeaderTimeoutTo 112 | { 113 | get { return Convert.ToInt32(ApplySpeedFactor(LeaderTimeoutToSetting)); } 114 | } 115 | 116 | public int FollowerTimeoutFrom 117 | { 118 | get { return Convert.ToInt32(ApplySpeedFactor(FollowerTimeoutFromSetting)); } 119 | } 120 | 121 | public int FollowerTimeoutTo 122 | { 123 | get { return Convert.ToInt32(ApplySpeedFactor(FollowerTimeoutToSetting)); } 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /RaftAlgorithm/RaftAlgorithm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {17D6F49D-15F2-4963-A83B-CAAB1F93CAA1} 8 | Library 9 | Properties 10 | RaftAlgorithm 11 | RaftAlgorithm 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 71 | -------------------------------------------------------------------------------- /NetworkModel/InProcNetwork/InProcServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetworkModel.InProcNetwork 8 | { 9 | public class InProcServer:INetworkServer 10 | { 11 | public InProcServer(InProcNetwork network) 12 | { 13 | this.Network = network; 14 | ClientChannels = new List(); 15 | } 16 | InProcNetwork Network; 17 | public bool StartListening(string address) 18 | { 19 | Address = address; 20 | var listeningChannel = new InProcSocket(Network, ChannelType.Listening) { LocalAddress = address }; 21 | listeningChannel.ParentServer = this; 22 | Network.RegisterListeningEndpoint(address, listeningChannel); 23 | ListeningChannel = listeningChannel; 24 | return true; 25 | } 26 | 27 | public string Address 28 | { 29 | get; 30 | private set; 31 | } 32 | 33 | public INetworkSocket ListeningChannel 34 | { 35 | get; 36 | internal set; 37 | } 38 | 39 | internal void AddClientChannel(InProcSocket newClient) 40 | { 41 | if (ClientConnected != null) 42 | ClientConnected(this, newClient); 43 | ClientChannels.Add(newClient); 44 | newClient.ParentServer = this; 45 | } 46 | internal void RemoveClientChannel(InProcSocket exisitingClient) 47 | { 48 | if (ClientDisconnected != null) 49 | ClientDisconnected(this, exisitingClient); 50 | exisitingClient.ParentServer = null; 51 | if (!ClientChannels.Remove(exisitingClient)) 52 | throw new Exception("Failed to remove socket from server client list: " + exisitingClient.ToString()); 53 | } 54 | 55 | public IList ClientChannels 56 | { 57 | get; 58 | private set; 59 | } 60 | 61 | public INetworkSocket GetSocketFromBacklog() 62 | { 63 | return new InProcSocket(Network, ChannelType.Server); 64 | } 65 | 66 | public event EventHandler ClientConnected; 67 | 68 | public event EventHandler ClientDisconnected; 69 | 70 | internal void RaiseMessageReceived(InProcSocket socket, object message) 71 | { 72 | if (MessageReceived != null) 73 | MessageReceived(this, new MessageReceivedArgs(socket, message)); 74 | } 75 | public event EventHandler MessageReceived; 76 | 77 | public void Dispose() 78 | { 79 | Stop(); 80 | } 81 | 82 | 83 | public bool Stop() 84 | { 85 | Network.UnregisterListeningEnpointFromNetwork(Address); 86 | ListeningChannel = null; 87 | 88 | List sockets = new List(); 89 | foreach (var clientSocket in ClientChannels) 90 | sockets.Add(clientSocket); 91 | 92 | for (int i = 0; i < sockets.Count; i++) 93 | { 94 | sockets[i].Close(); 95 | } 96 | return true; 97 | } 98 | 99 | 100 | 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /RaftAlgorithm/RaftEventResult.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm.Messages; 2 | using System; 3 | 4 | namespace RaftAlgorithm 5 | { 6 | /// 7 | /// Result of eny operation performed on raft algorithm like receiving message, elapsing raft timer 8 | /// 9 | public class RaftEventResult 10 | { 11 | /// 12 | /// Create RaftEventResult object 13 | /// 14 | /// Message to broadcast or reply 15 | /// True of message need broadcasting instead of replying 16 | public RaftEventResult(RaftMessageBase raftMessage, bool doBroadcast) 17 | { 18 | this.DoBroadcast = doBroadcast; 19 | this.MessageToSend = raftMessage; 20 | } 21 | /// 22 | /// Create event that will result in replying to port that request came from 23 | /// 24 | /// 25 | /// 26 | public static RaftEventResult ReplyMessage(RaftMessageBase raftMessage) 27 | { 28 | return new RaftEventResult(raftMessage, false); 29 | } 30 | /// 31 | /// Create event that will result in broadcasting message 32 | /// 33 | /// 34 | /// 35 | public static RaftEventResult BroadcastMessage(RaftMessageBase raftMessage) 36 | { 37 | return new RaftEventResult(raftMessage, true); 38 | } 39 | 40 | /// 41 | /// Create empty Raft event result 42 | /// 43 | public static RaftEventResult Empty 44 | { 45 | get 46 | { 47 | return new RaftEventResult(null, false); 48 | } 49 | } 50 | /// 51 | /// Returns true if Raft algorithm requests timer to bet set 52 | /// 53 | public bool TimerSet 54 | { 55 | get; 56 | private set; 57 | } 58 | /// 59 | /// Value of timer 60 | /// 61 | public int TimerValue 62 | { 63 | get; 64 | private set; 65 | } 66 | static readonly Random rnd = new Random(); 67 | 68 | /// 69 | /// Request to set raft timer to random value between timerFrom and timerTo 70 | /// 71 | /// 72 | /// 73 | /// 74 | public RaftEventResult SetTimer(int timerFrom, int timerTo) 75 | { 76 | if (TimerSet) 77 | throw new InvalidOperationException("Timer already set"); 78 | TimerSet = true; 79 | TimerValue = rnd.Next(timerFrom, timerTo); 80 | return this; 81 | } 82 | 83 | /// 84 | /// Massage to reply or broadcast 85 | /// 86 | public RaftMessageBase MessageToSend 87 | { 88 | get; 89 | private set; 90 | } 91 | /// 92 | /// True of MessageToSend needs to be broadcasted 93 | /// 94 | public bool DoBroadcast 95 | { 96 | get; 97 | private set; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /RaftDemo/Views/AppView.xaml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 60 | 61 | 62 | Edit labels 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /TaskSchedulerRun/HighPrecisionTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using CircularBuffer; 6 | 7 | namespace Animatroller.Framework.Utility 8 | { 9 | public class HighPrecisionTimer : IDisposable 10 | { 11 | public class TickEventArgs : EventArgs 12 | { 13 | public TimeSpan Duration { get; private set; } 14 | public long TotalTicks { get; private set; } 15 | public int NextTickIn { get; set; } 16 | public TickEventArgs(TimeSpan totalDuration, long totalTicks) 17 | { 18 | this.Duration = totalDuration; 19 | this.TotalTicks = totalTicks; 20 | } 21 | } 22 | public event EventHandler Tick; 23 | protected CircularBuffer.CircularBuffer tickTiming; 24 | protected CancellationTokenSource cancelSource; 25 | 26 | public HighPrecisionTimer(int interval) 27 | { 28 | if (interval < 1) 29 | throw new ArgumentOutOfRangeException(); 30 | 31 | // System.Diagnostics.Trace.Assert(interval >= 10, "Not reliable/tested, may use too much CPU"); 32 | 33 | cancelSource = new CancellationTokenSource(); 34 | 35 | // Used to report timing accuracy for 1 sec, running total 36 | tickTiming = new CircularBuffer(1000 / interval, true); 37 | 38 | var watch = System.Diagnostics.Stopwatch.StartNew(); 39 | long durationMs = 0; 40 | long totalTicks = 0; 41 | long nextStop = interval; 42 | long lastReport = 0; 43 | 44 | var task = new Task(() => 45 | { 46 | while (!this.cancelSource.IsCancellationRequested) 47 | { 48 | long msLeft = nextStop - watch.ElapsedMilliseconds; 49 | if (msLeft <= 0) 50 | { 51 | durationMs = watch.ElapsedMilliseconds; 52 | totalTicks = durationMs / interval; 53 | 54 | tickTiming.Put((int)(durationMs - nextStop)); 55 | 56 | if (durationMs - lastReport >= 1000) 57 | { 58 | // Report 59 | 60 | 61 | lastReport = durationMs; 62 | } 63 | 64 | var eventArgs = new TickEventArgs(TimeSpan.FromMilliseconds(durationMs), totalTicks); 65 | 66 | var handler = Tick; 67 | if (handler != null) 68 | handler(this, eventArgs); 69 | 70 | if(eventArgs.NextTickIn> 0) 71 | interval = eventArgs.NextTickIn; 72 | // Calculate when the next stop is. If we're too slow on the trigger then we'll skip ticks 73 | nextStop = watch.ElapsedMilliseconds + interval; 74 | } 75 | else if (msLeft < 16) 76 | { 77 | System.Threading.SpinWait.SpinUntil(() => watch.ElapsedMilliseconds >= nextStop); 78 | continue; 79 | } 80 | 81 | System.Threading.Thread.Sleep(1); 82 | } 83 | }, cancelSource.Token, TaskCreationOptions.LongRunning); 84 | 85 | task.Start(); 86 | } 87 | 88 | public void Dispose() 89 | { 90 | this.cancelSource.Cancel(); 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /CaliDiagram/Views/EdgeView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | using CaliDiagram.ViewModels; 16 | using System.Windows.Media.Animation; 17 | 18 | namespace CaliDiagram.Views 19 | { 20 | /// 21 | /// Interaction logic for EdgeView.xaml 22 | /// 23 | public partial class EdgeView : Shape 24 | { 25 | public EdgeView() 26 | { 27 | Loaded += ConnectionView_Loaded; 28 | } 29 | 30 | private ConnectionViewModel vm; 31 | void ConnectionView_Loaded(object sender, RoutedEventArgs e) 32 | { 33 | vm = DataContext as ConnectionViewModel; 34 | if (vm != null) 35 | vm.UpdateConnection(); 36 | 37 | } 38 | 39 | public Point FromPoint 40 | { 41 | get { return (Point)GetValue(FromPointProperty); } 42 | set { SetValue(FromPointProperty, value); } 43 | } 44 | 45 | public static readonly DependencyProperty FromPointProperty = 46 | DependencyProperty.Register("FromPoint", typeof(Point), typeof(EdgeView), 47 | new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender)); 48 | 49 | 50 | public Point ToPoint 51 | { 52 | get { return (Point)GetValue(ToPointProperty); } 53 | set { SetValue(ToPointProperty, value); } 54 | } 55 | 56 | public static readonly DependencyProperty ToPointProperty = 57 | DependencyProperty.Register("ToPoint", typeof(Point), typeof(EdgeView), 58 | new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender)); 59 | 60 | protected override Geometry DefiningGeometry 61 | { 62 | get 63 | { 64 | StreamGeometry geometry = new StreamGeometry(); 65 | geometry.FillRule = FillRule.EvenOdd; 66 | 67 | using (StreamGeometryContext context = geometry.Open()) 68 | InternalDrawArrowGeometry(context); 69 | 70 | geometry.Freeze(); 71 | 72 | return geometry; 73 | } 74 | } 75 | 76 | /// 77 | /// Draws an Arrow 78 | /// 79 | private void InternalDrawArrowGeometry(StreamGeometryContext context) 80 | { 81 | vm = DataContext as ConnectionViewModel; 82 | if (vm == null) 83 | return; 84 | 85 | if(vm.Type == EdgeLineType.Line) 86 | { 87 | context.BeginFigure(FromPoint, false, false); 88 | 89 | context.LineTo(ToPoint, true, false); 90 | } 91 | else if (vm.Type == EdgeLineType.Bezier) 92 | { 93 | var bezierPoints = vm.GetBezierPoints(); 94 | 95 | context.BeginFigure(bezierPoints[0], false, false); 96 | context.BezierTo(bezierPoints[1], bezierPoints[2], bezierPoints[3], true, true); 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /RaftAlgorithm/States/Leader.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm.Messages; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace RaftAlgorithm.States 9 | { 10 | public class Leader : RaftStateBase 11 | { 12 | public Leader(RaftNode node):base(node) 13 | { 14 | 15 | } 16 | public override RaftNodeState State 17 | { 18 | get { return RaftNodeState.Leader; } 19 | } 20 | /// 21 | /// Index of highest log entry known to be commited(initialized to 0, increases monotonically) 22 | /// 23 | readonly Dictionary NextIndex = new Dictionary(); 24 | /// 25 | /// For each server, index of highest log entry applied to state machine(initialized to 0, increases monotonically) 26 | /// 27 | readonly Dictionary MatchIndex = new Dictionary(); 28 | 29 | 30 | public override RaftEventResult EnterState() 31 | { 32 | return BroadcastAppendEntries(); 33 | } 34 | 35 | RaftEventResult BroadcastAppendEntries() 36 | { 37 | Node.RaftEventListener.OnAppendEntries(); 38 | 39 | var appendEntriesMessage = new AppendEntriesRPC(Node.PersistedState.CurrentTerm, Node.Id); 40 | appendEntriesMessage.LeaderCommit = Node.CurrentIndex; 41 | //for (int i=Node.CurrentIndex; i < Node.Log.Count; i++) 42 | //{ 43 | // if (appendEntriesMessage.LogEntries == null) 44 | // appendEntriesMessage.LogEntries = new List>(); 45 | // appendEntriesMessage.LogEntries.Add(Node.Log[i]); 46 | //} 47 | return RaftEventResult.BroadcastMessage(appendEntriesMessage).SetTimer(Node.RaftSettings.LeaderTimeoutFrom, Node.RaftSettings.LeaderTimeoutTo); 48 | } 49 | 50 | public override RaftEventResult OnTimeout() 51 | { 52 | return BroadcastAppendEntries(); 53 | } 54 | 55 | public override RaftEventResult ReceiveRequestVote(RequestVote requestVote) 56 | { 57 | if(requestVote.CandidateTerm > CurrentTerm) 58 | { 59 | return Node.TranslateToState(RaftNodeState.Follower, requestVote); 60 | } 61 | return RaftEventResult.ReplyMessage(DenyVote); 62 | } 63 | 64 | public override RaftEventResult ReceiveRequestVoteResponse(RequestVoteResponse requestVoteResponse) 65 | { 66 | // got vote but we dont care because we are leader already 67 | return RaftEventResult.Empty; 68 | } 69 | 70 | public override RaftEventResult ReceiveAppendEntries(AppendEntriesRPC appendEntries) 71 | { 72 | if (appendEntries.LeaderTerm > CurrentTerm) 73 | { 74 | return Node.TranslateToState(RaftNodeState.Follower, appendEntries); 75 | } 76 | return RaftEventResult.Empty; 77 | } 78 | 79 | public override RaftEventResult ReceiveAppendEntriesResponse(AppendEntriesResponse appendEntriesResponse) 80 | { 81 | if (appendEntriesResponse.FollowerTerm > CurrentTerm) 82 | { 83 | return Node.TranslateToState(RaftNodeState.Follower); 84 | } 85 | return RaftEventResult.Empty; 86 | } 87 | public override string ToString() 88 | { 89 | return "Leader"; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /CaliDiagram/Views/DiagramView.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Add node1 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /RaftDemo/Views/SimulationSettingsView.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Sound 19 | Packet visuals 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 45 | 46 | 47 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /NetworkModel/Actors/ActorBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NetworkModel.InProcNetwork; 7 | 8 | namespace NetworkModel.Actors 9 | { 10 | /// 11 | /// Base actor class 12 | /// 13 | public partial class ActorBase : IDisposable 14 | { 15 | public class ClientInfo 16 | { 17 | public string Address; 18 | public NetworkClient NetworkClient; 19 | } 20 | 21 | public ActorBase(INetworkModel networkModel) 22 | { 23 | this.NetworkModel = networkModel; 24 | NetworkClientContexts = new List(); 25 | Channels = new List(); 26 | } 27 | 28 | /// 29 | /// Network model used by actor 30 | /// 31 | public INetworkModel NetworkModel { get; private set; } 32 | 33 | /// 34 | /// List of clientInfo contexts [clientInfo - this actor to server - other actor] connections 35 | /// 36 | public List NetworkClientContexts { get; private set; } 37 | 38 | /// 39 | /// Actor state 40 | /// 41 | public ActorState State { get; private set; } 42 | 43 | public List Channels { get; private set; } 44 | /// 45 | /// Start actor 46 | /// 47 | public virtual void Start() 48 | { 49 | State = ActorState.Starting; 50 | RequestStartEventLoop(); 51 | 52 | foreach (var clientInfo in NetworkClientContexts) 53 | { 54 | CreateNetworkClient(clientInfo); 55 | } 56 | } 57 | 58 | /// 59 | /// Return numbers of clientInfo attempting to connect to other actors 60 | /// 61 | public int WorkingClientCount 62 | { 63 | get { return NetworkClientContexts.Count(c => c.NetworkClient != null); } 64 | } 65 | 66 | 67 | /// 68 | /// Stop actor 69 | /// 70 | public virtual void Stop() 71 | { 72 | State = ActorState.Stopping; 73 | RequestStopEventLoop(); 74 | } 75 | 76 | void CreateNetworkClient(ClientInfo clientInfo) 77 | { 78 | if(clientInfo.NetworkClient != null) 79 | throw new InvalidOperationException("NetworkClient already created for address " + clientInfo.Address); 80 | 81 | NetworkClient networkClient = new NetworkClient(NetworkModel) {MaxConnectAttempts = -1}; 82 | networkClient.StartConnectingTo(clientInfo.Address); 83 | networkClient.ConnectionStateChanged += networkClient_ConnectionStateChanged; 84 | clientInfo.NetworkClient = networkClient; 85 | } 86 | 87 | void networkClient_ConnectionStateChanged(object sender, bool e) 88 | { 89 | throw new NotImplementedException(); 90 | } 91 | 92 | 93 | public void AddConnectionTo(string actorAddress) 94 | { 95 | ClientInfo client = new ClientInfo {Address = actorAddress}; 96 | NetworkClientContexts.Add(client); 97 | if (State == ActorState.Started) 98 | CreateNetworkClient(client); 99 | 100 | } 101 | 102 | protected void SendMessage(ActorChannel channel, object message) 103 | { 104 | channel.Socket.SendMessage(message); 105 | } 106 | 107 | protected virtual void BroadcastMessage(object message) 108 | { 109 | throw new NotImplementedException(); 110 | } 111 | 112 | public void Dispose() 113 | { 114 | 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /RaftAlgorithm/States/Follower.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm.Messages; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace RaftAlgorithm.States 9 | { 10 | public class Follower : RaftStateBase 11 | { 12 | public Follower(RaftNode node) 13 | : base(node) 14 | { 15 | 16 | } 17 | public override RaftNodeState State 18 | { 19 | get { return RaftNodeState.Follower; } 20 | } 21 | public override string ToString() 22 | { 23 | return "Follower"; 24 | } 25 | static Random rnd = new Random(); 26 | public override RaftEventResult EnterState() 27 | { 28 | // Start new election(translate to candidate) of no sign of leader for random time specified here 29 | return RaftEventResult.Empty.SetTimer(Node.RaftSettings.FollowerTimeoutFrom, Node.RaftSettings.FollowerTimeoutTo); 30 | } 31 | 32 | public override RaftEventResult OnTimeout() 33 | { 34 | // translate to candidate and start new election 35 | return Node.TranslateToState(RaftNodeState.Candidate); 36 | } 37 | 38 | public override RaftEventResult ReceiveRequestVote(RequestVote requestVote) 39 | { 40 | // we have more recent term so we dont vote 41 | if(requestVote.CandidateTerm < CurrentTerm) 42 | { 43 | return RaftEventResult.ReplyMessage(DenyVote); 44 | } 45 | 46 | if(requestVote.CandidateTerm > CurrentTerm) 47 | { 48 | CurrentTerm = requestVote.CandidateTerm; 49 | } 50 | // if haven't voted before 51 | if (Node.PersistedState.VotedFor == null || Node.PersistedState.VotedFor == requestVote.CandidateId) 52 | { 53 | Node.PersistedState.VotedFor = requestVote.CandidateId; 54 | return RaftEventResult.ReplyMessage(GrantVote).SetTimer(Node.RaftSettings.FollowerTimeoutFrom * 2, Node.RaftSettings.FollowerTimeoutTo * 2); 55 | } 56 | return RaftEventResult.Empty; 57 | } 58 | 59 | public override RaftEventResult ReceiveRequestVoteResponse(RequestVoteResponse requestVoteResponse) 60 | { 61 | return RaftEventResult.Empty; 62 | } 63 | 64 | public override RaftEventResult ReceiveAppendEntries(AppendEntriesRPC appendEntries) 65 | { 66 | //Reply false if term from append entires < currentTerm (§5.1) 67 | if (appendEntries.LeaderTerm < CurrentTerm) 68 | { 69 | var falseResponse = new AppendEntriesResponse(CurrentTerm, Node.Id, false); 70 | return RaftEventResult.ReplyMessage(falseResponse).SetTimer(Node.RaftSettings.FollowerTimeoutFrom, Node.RaftSettings.FollowerTimeoutTo); 71 | } 72 | 73 | CurrentTerm = appendEntries.LeaderTerm; 74 | 75 | //if (appendEntries.LogEntries != null) 76 | // for (int i = 0; i < appendEntries.LogEntries.Count; i++) 77 | // { 78 | // if (appendEntries.LogEntries[i].CommitIndex > Node.Log.Count) 79 | // { 80 | // Node.Log.Add(appendEntries.LogEntries[i]); 81 | // Node.CurrentIndex = appendEntries.LogEntries[i].CommitIndex; 82 | // } 83 | // } 84 | 85 | var aeResponse = new AppendEntriesResponse(CurrentTerm, Node.Id, true ); 86 | return RaftEventResult.ReplyMessage(aeResponse).SetTimer(Node.RaftSettings.FollowerTimeoutFrom, Node.RaftSettings.FollowerTimeoutTo); 87 | } 88 | 89 | public override RaftEventResult ReceiveAppendEntriesResponse(AppendEntriesResponse appendEntriesResponse) 90 | { 91 | return RaftEventResult.Empty; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /CaliDiagram/Serialization/DiagramXmlSerializer.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.Model; 2 | using CaliDiagram.ViewModels; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace CaliDiagram.Serialization 10 | { 11 | /// 12 | /// Saving and loading diagram as Xml file 13 | /// 14 | public class DiagramXmlSerializer 15 | { 16 | 17 | public DiagramXmlSerializer(DiagramViewModel diagramViewModel) 18 | { 19 | this.diagramViewModel = diagramViewModel; 20 | xmlSettings = new XmlSettings(diagramViewModel.Definition.NodeTypes); 21 | 22 | } 23 | DiagramViewModel diagramViewModel; 24 | XmlSettings xmlSettings; 25 | 26 | public void SaveDiagram(string filename) 27 | { 28 | DiagramModel diagramModel = new DiagramModel(); 29 | Dictionary nodeDictionary = new Dictionary(); 30 | foreach (var node in diagramViewModel.Nodes) 31 | { 32 | DiagramNodeBase diagramNode = diagramViewModel.Definition.ViewModelToModel(node); 33 | if (diagramNode == null) 34 | continue; 35 | diagramModel.Nodes.Add(diagramNode); 36 | nodeDictionary.Add(node, diagramNode); 37 | 38 | } 39 | 40 | foreach (var edge in diagramViewModel.Edges) 41 | { 42 | diagramModel.Edges.Add(new DiagramConnection() 43 | { 44 | From = nodeDictionary[edge.From], 45 | To = nodeDictionary[edge.To] 46 | }); 47 | } 48 | xmlSettings.SaveModel(diagramModel, filename); 49 | } 50 | 51 | public void LoadDiagram(string filename) 52 | { 53 | DiagramModel model = xmlSettings.ModelFromSettings(filename); 54 | 55 | diagramViewModel.ClearDiagram(); 56 | 57 | using (var bm = new DiagramBatchMode(diagramViewModel)) 58 | { 59 | Dictionary nodeDictionary = new Dictionary(); 60 | foreach (var node in model.Nodes) 61 | { 62 | NodeBaseViewModel nodeViewModel = diagramViewModel.Definition.ModelToViewModel(node); 63 | if (nodeViewModel == null) 64 | continue; 65 | 66 | diagramViewModel.AddNode(nodeViewModel, node.Location); 67 | 68 | nodeDictionary.Add(node, nodeViewModel); 69 | 70 | } 71 | // Force rendering so we can have sizes of all nodes 72 | // diagramViewModel.ForceRedraw(); 73 | 74 | foreach (var edge in model.Edges) 75 | { 76 | diagramViewModel.AddConnection(nodeDictionary[edge.From], nodeDictionary[edge.To]); 77 | } 78 | // Render again so we can have sizes of attach descriptors 79 | diagramViewModel.ForceRedraw(); 80 | 81 | Console.WriteLine("Model loaded"); 82 | 83 | // dont need to call RaiseInitialize, it was allready called in AddNode 84 | //foreach (var node in diagramViewModel.Nodes) 85 | // node.RaiseInitialize(); 86 | 87 | foreach (var node in diagramViewModel.AttachDescriptors) 88 | node.RaiseInitialize(); 89 | 90 | diagramViewModel.ForceRedraw(); 91 | 92 | 93 | } 94 | 95 | foreach (var conn in diagramViewModel.Edges) 96 | conn.UpdateConnection(); 97 | 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /RaftAlgorithm/States/Candicate.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm.Messages; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace RaftAlgorithm.States 9 | { 10 | public class Candicate : RaftStateBase 11 | { 12 | public Candicate(RaftNode node) 13 | : base(node) 14 | { 15 | 16 | } 17 | public override RaftNodeState State 18 | { 19 | get { return RaftNodeState.Candidate; } 20 | } 21 | public override string ToString() 22 | { 23 | return "Candidate"; 24 | } 25 | 26 | public override RaftEventResult EnterState() 27 | { 28 | return StartNewElection(); 29 | } 30 | 31 | RaftEventResult StartNewElection() 32 | { 33 | VoteTable.Clear(); 34 | Node.RaftEventListener.OnElectionStarted(); 35 | // increment current term 36 | Node.PersistedState.CurrentTerm++; 37 | // vote for self 38 | ProcessVote(Node.Id); 39 | Node.PersistedState.VotedFor = Node.Id; 40 | // send request votes to all servers 41 | var requestVote = new RequestVote() { CandidateId = Node.Id, CandidateTerm = CurrentTerm }; 42 | return RaftEventResult.BroadcastMessage(requestVote).SetTimer(Node.RaftSettings.FollowerTimeoutFrom, Node.RaftSettings.FollowerTimeoutTo); 43 | } 44 | 45 | 46 | 47 | public override RaftEventResult OnTimeout() 48 | { 49 | return StartNewElection(); 50 | } 51 | 52 | public override RaftEventResult ReceiveRequestVote(RequestVote requestVote) 53 | { 54 | if (requestVote.CandidateId == Node.Id) 55 | return RaftEventResult.Empty; 56 | 57 | 58 | bool voteGranted = false; 59 | if (requestVote.CandidateTerm >= CurrentTerm) 60 | { 61 | // Node.CurrentTerm = requestVote.CandidateTerm; 62 | return Node.TranslateToState(RaftNodeState.Follower, requestVote); 63 | } 64 | return RaftEventResult.ReplyMessage(DenyVote); 65 | } 66 | Dictionary VoteTable = new Dictionary(); 67 | 68 | void ProcessVote(string voterId) 69 | { 70 | if (!VoteTable.ContainsKey(voterId)) 71 | VoteTable.Add(voterId, true); 72 | } 73 | 74 | public override RaftEventResult ReceiveRequestVoteResponse(RequestVoteResponse requestVoteResponse) 75 | { 76 | if(requestVoteResponse.CurrentTerm > CurrentTerm) 77 | { 78 | return Node.TranslateToState(RaftNodeState.Follower, requestVoteResponse); 79 | } 80 | 81 | if (requestVoteResponse.VoteGranted) 82 | { 83 | ProcessVote(requestVoteResponse.VoterId); 84 | } 85 | 86 | int majority = (Node.RaftSettings.ClusterSize / 2) + 1; 87 | if (VoteTable.Count >= majority) 88 | { 89 | return Node.TranslateToState(RaftNodeState.Leader); 90 | } 91 | return RaftEventResult.Empty; 92 | } 93 | 94 | public override RaftEventResult ReceiveAppendEntries(AppendEntriesRPC appendEntries) 95 | { 96 | if (appendEntries.LeaderTerm >= CurrentTerm) 97 | { 98 | return Node.TranslateToState(RaftNodeState.Follower, appendEntries ); 99 | } 100 | return RaftEventResult.Empty; 101 | } 102 | 103 | public override RaftEventResult ReceiveAppendEntriesResponse(AppendEntriesResponse appendEntriesResponse) 104 | { 105 | return Node.TranslateToState(RaftNodeState.Follower); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /CaliDiagram/ViewModels/DiagramHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace CaliDiagram.ViewModels 9 | { 10 | public class DiagramHelpers 11 | { 12 | public static Point GetAttachmentLocation(NodeBaseViewModel control, Point fromPoint, AttachDirection pos) 13 | { 14 | switch (pos) 15 | { 16 | case AttachDirection.Top: 17 | return new Point(fromPoint.X - control.Size.Width / 2, fromPoint.Y - control.Size.Height/2); 18 | case AttachDirection.Right: 19 | return new Point(fromPoint.X - control.Size.Width / 2 , fromPoint.Y - (control.Size.Height / 2)); 20 | case AttachDirection.Bottom: 21 | return new Point(fromPoint.X - control.Size.Width / 2, fromPoint.Y - control.Size.Height / 2); 22 | case AttachDirection.Left: 23 | return new Point(fromPoint.X - control.Size.Width/2, fromPoint.Y - control.Size.Height / 2); 24 | default: 25 | throw new ArgumentException(); 26 | } 27 | 28 | } 29 | public static Point GetAttachmentLocationOld(NodeBaseViewModel control, Point fromPoint, AttachDirection pos) 30 | { 31 | switch (pos) 32 | { 33 | case AttachDirection.Top: 34 | return new Point(fromPoint.X - control.Size.Width / 2, fromPoint.Y - control.Size.Height); 35 | case AttachDirection.Right: 36 | return new Point(fromPoint.X, fromPoint.Y - (control.Size.Height / 2)); 37 | case AttachDirection.Bottom: 38 | return new Point(fromPoint.X - control.Size.Width / 2, fromPoint.Y); 39 | case AttachDirection.Left: 40 | return new Point(fromPoint.X - control.Size.Width, fromPoint.Y - control.Size.Height / 2); 41 | default: 42 | throw new ArgumentException(); 43 | } 44 | 45 | } 46 | 47 | public static Point GetMiddlePoint(AttachDirection dir, Rect rec) 48 | { 49 | if (dir == AttachDirection.Top) 50 | return new Point(rec.X + rec.Width / 2, rec.Y); 51 | if (dir == AttachDirection.Right) 52 | return new Point(rec.X + rec.Width, rec.Y + rec.Height / 2); 53 | if (dir == AttachDirection.Bottom) 54 | return new Point(rec.X + rec.Width / 2, rec.Y + rec.Height); 55 | if (dir == AttachDirection.Left) 56 | return new Point(rec.X, rec.Y + rec.Height / 2); 57 | throw new ArgumentException(); 58 | } 59 | 60 | public static Point[] AttachPoints(Rect rect) 61 | { 62 | return new Point[] 63 | { 64 | DiagramHelpers.GetMiddlePoint(AttachDirection.Top, rect), 65 | DiagramHelpers.GetMiddlePoint(AttachDirection.Right, rect), 66 | DiagramHelpers.GetMiddlePoint(AttachDirection.Bottom, rect), 67 | DiagramHelpers.GetMiddlePoint(AttachDirection.Left, rect) 68 | }; 69 | 70 | } 71 | 72 | public static double DistanceBetweenPoints(Point a, Point b) 73 | { 74 | return (Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2)); 75 | } 76 | public static double GetAngleBetweenRects(Rect fromRect, Rect toRect) 77 | { 78 | var fromMiddlePoint = new Point(fromRect.X + fromRect.Width / 2.0, fromRect.Y + fromRect.Height / 2.0); 79 | var toMiddlePoint = new Point(toRect.X + toRect.Width / 2.0, toRect.Y + toRect.Height / 2.0); 80 | const double Rad2Deg = 180.0 / Math.PI; 81 | double angle = Math.Atan2(fromMiddlePoint.X - toMiddlePoint.X, fromMiddlePoint.Y - toMiddlePoint.Y) * Rad2Deg + 90; 82 | if (angle < 0) 83 | angle = 360 + angle; 84 | return angle; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /NetworkModel/NetworkModel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {44CA1876-B5BE-4438-A0DD-BB3A7B6EED5F} 8 | Library 9 | Properties 10 | NetworkModel 11 | NetworkModel 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 82 | -------------------------------------------------------------------------------- /NetworkModel/InProcNetwork/InProcNetwork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace NetworkModel.InProcNetwork 7 | { 8 | using TaskScheduling; 9 | public class InProcNetwork : INetworkModel, IDisposable 10 | { 11 | public InProcNetwork() 12 | { 13 | ConnectionEstablishLatency = 0; 14 | TaskScheduler = new TaskScheduler(); 15 | Exceptions = new List(); 16 | } 17 | 18 | /// 19 | /// How much time it takes to establish connection(dest socket-> conn established) 20 | /// 21 | public int ConnectionEstablishLatency { get; set; } 22 | /// 23 | /// How much time it takes to close connection(dest socket->closed) 24 | /// 25 | public int ConnectionCloseLatency { get; set; } 26 | /// 27 | /// default latency for packets 28 | /// 29 | public int ConnectionDefaultLatency { get; set; } 30 | 31 | /// 32 | /// Listening server sockets 33 | /// 34 | internal Dictionary ListeningSockets = new Dictionary(); 35 | 36 | /// 37 | /// SocketIds [local_address, remote_address] -> Socket that have established state 38 | /// 39 | internal Dictionary EstablishedSockets = new Dictionary(); 40 | 41 | /// 42 | /// SocketIds [client_address,server_address] -> Socket that are in 'connecting' state 43 | /// 44 | internal Dictionary ConnectingSockets = new Dictionary(); 45 | 46 | public int ListeningSocketCount 47 | { 48 | get { return ListeningSockets.Count; } 49 | } 50 | public int ConnectedSocketCount 51 | { 52 | get { return EstablishedSockets.Count; } 53 | } 54 | volatile int clientNo = 1; 55 | internal string GetNextClientSocketAddress() 56 | { 57 | return string.Format("{0}", clientNo++); 58 | } 59 | 60 | public TaskScheduler TaskScheduler { get; private set; } 61 | 62 | internal void RegisterListeningEndpoint(string addres, InProcSocket channel) 63 | { 64 | if (channel.Type != ChannelType.Listening) 65 | throw new Exception("Only listening socket can be registered"); 66 | InProcSocket existingServer = null; 67 | if (ListeningSockets.TryGetValue(addres, out existingServer)) 68 | throw new Exception(string.Format("Address {0} already in use")); 69 | 70 | ListeningSockets.Add(addres, channel); 71 | } 72 | internal bool UnregisterListeningEnpointFromNetwork(string address) 73 | { 74 | return ListeningSockets.Remove(address); 75 | } 76 | 77 | internal int GetConnectionDelay(InProcSocket source, InProcSocket destination) 78 | { 79 | return ConnectionDefaultLatency; 80 | } 81 | 82 | public INetworkSocket CreateClientSocket(string socketAddress = null) 83 | { 84 | if (socketAddress == null) 85 | socketAddress = ":" + GetNextClientSocketAddress(); 86 | 87 | return new InProcSocket(this, ChannelType.Client) { LocalAddress = socketAddress }; 88 | } 89 | 90 | public INetworkServer CreateServer(string socketAddress, bool startListening = true) 91 | { 92 | var server = new InProcServer(this); 93 | if(startListening) 94 | server.StartListening(socketAddress); 95 | return server; 96 | } 97 | 98 | public void Dispose() 99 | { 100 | TaskScheduler.Dispose(); 101 | } 102 | 103 | /// 104 | /// Exceptions occured in other threads 105 | /// 106 | public List Exceptions { get; private set; } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /NetworkModel/InProcNetwork/TaskScheduling/TaskScheduler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace NetworkModel.InProcNetwork.TaskScheduling 10 | { 11 | public class TaskScheduler :IDisposable 12 | { 13 | Thread taskSchedulingThread = null; 14 | public TaskScheduler() 15 | { 16 | StartTaskSchedulerThread(); 17 | Exceptions = new List(); 18 | } 19 | public List Exceptions 20 | { 21 | get; 22 | private set; 23 | } 24 | void StartTaskSchedulerThread() 25 | { 26 | if (Running == false) 27 | { 28 | Running = true; 29 | taskSchedulingThread = new Thread(TaskSchedlulerLoop); 30 | taskSchedulingThread.IsBackground = true; 31 | taskSchedulingThread.Start(); 32 | } 33 | } 34 | List tasks = new List(); 35 | 36 | public void SchedluleTask(Action task, TimeSpan timeFromNow) 37 | { 38 | //Debug.WriteLine("scheduleTask"); 39 | TaskSchedlulerTask newTask = new TaskSchedlulerTask() 40 | { 41 | SchedluledTime = DateTime.Now, 42 | ExecuteAfter = timeFromNow, 43 | Function = task 44 | }; 45 | lock(tasks) 46 | tasks.Add(newTask); 47 | 48 | 49 | ev.Set(); 50 | } 51 | object _sync = new object(); 52 | 53 | volatile bool Running = false; 54 | AutoResetEvent ev = new AutoResetEvent(false); 55 | 56 | void TaskSchedlulerLoop(object o) 57 | { 58 | 59 | while (Running) 60 | { 61 | int waitTime = -1; 62 | 63 | List tasksOrderedByTime = null; 64 | 65 | // order tasks by run time 66 | lock (tasks) 67 | tasksOrderedByTime = tasks.OrderBy(t => t.RunIn).ToList(); 68 | 69 | // pick task closest in time 70 | TaskSchedlulerTask closestTask = null; 71 | if (tasksOrderedByTime != null && tasksOrderedByTime.Count > 0) 72 | closestTask = tasksOrderedByTime[0]; 73 | 74 | 75 | if (closestTask != null) 76 | waitTime = (int)closestTask.RunIn; 77 | 78 | if (waitTime == -1) 79 | ev.WaitOne(); 80 | else 81 | ev.WaitOne(waitTime); 82 | 83 | if (!Running) 84 | return; 85 | 86 | 87 | List tasksToRunNow = null; 88 | lock (tasks) 89 | { 90 | tasksToRunNow = tasks.Where(t => t.RunIn <= 0).ToList(); 91 | foreach (var taskToRemove in tasksToRunNow) 92 | tasks.Remove(taskToRemove); 93 | } 94 | 95 | foreach (TaskSchedlulerTask t in tasksToRunNow) 96 | { 97 | RunTask(t); 98 | } 99 | 100 | 101 | } 102 | } 103 | 104 | public event EventHandler OnException; 105 | 106 | bool RunTask(TaskSchedlulerTask task) 107 | { 108 | try 109 | { 110 | TimeSpan tsFromStart = DateTime.Now - task.SchedluledTime; 111 | task.Function(); 112 | return true; 113 | } 114 | catch(Exception ex) 115 | { 116 | if (OnException != null) 117 | OnException(this, ex); 118 | Trace.TraceWarning("Failed to run task"); 119 | Exceptions.Add(ex); 120 | return false; 121 | } 122 | } 123 | 124 | public void Dispose() 125 | { 126 | Running = false; 127 | ev.Set(); 128 | taskSchedulingThread.Join(); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /RaftDemo/Model/RaftHost.cs: -------------------------------------------------------------------------------- 1 | using RaftAlgorithm; 2 | using RaftAlgorithm.Messages; 3 | using RaftAlgorithm.States; 4 | using RaftDemo.NodeSoftware; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using NetworkModel; 11 | 12 | namespace RaftDemo.Model 13 | { 14 | public class RaftHost : NodeSoftwareBase 15 | { 16 | public RaftHost(INetworkModel networkModel, IRaftEventListener raftEventListener, IRaftNodeSettings raftSettings, string Id): 17 | base(networkModel) 18 | { 19 | this.Id = Id; 20 | if (Id == null) 21 | throw new ArgumentException("Id"); 22 | Raft = new RaftNode(raftEventListener, raftSettings, Id); 23 | Server = networkModel.CreateServer(Id, startListening: false); 24 | } 25 | INetworkServer Server { get; set; } 26 | public RaftNode Raft 27 | { 28 | get; 29 | private set; 30 | } 31 | 32 | TimeoutTimer RaftTimer 33 | { 34 | get; 35 | set; 36 | } 37 | 38 | protected override void OnInitialized() 39 | { 40 | base.OnInitialized(); 41 | Server.StartListening(Id); 42 | RaftTimer = new TimeoutTimer(this); 43 | var raftOperationResult = Raft.Start(); 44 | ProcessRaftResult(raftOperationResult); 45 | } 46 | protected override void OnDestroyed() 47 | { 48 | RaftTimer.Dispose(); 49 | Server.Dispose(); 50 | } 51 | INetworkSocket leaderChannel; 52 | protected override void OnMessageReceived(INetworkSocket channel, object message) 53 | { 54 | RaftMessageBase raftMessage = message as RaftMessageBase; 55 | if (raftMessage is AppendEntriesRPC) 56 | leaderChannel = channel; 57 | 58 | Message messageFromClient = message as Message; 59 | if(messageFromClient != null) 60 | { 61 | if(Raft.State == RaftNodeState.Leader) 62 | { 63 | raftMessage = new ClientRequestRPC() 64 | { 65 | Message = messageFromClient.Operation, 66 | SequenceNumber = 0 67 | }; 68 | } 69 | else 70 | { 71 | if(leaderChannel != null) 72 | SendMessage(leaderChannel, messageFromClient); 73 | // forward message to leader 74 | } 75 | } 76 | 77 | if (raftMessage != null) 78 | { 79 | var raftOperationResult = Raft.OnMessageReceived(raftMessage); 80 | ProcessRaftResult(raftOperationResult, channel); 81 | } 82 | 83 | 84 | } 85 | protected override void OnTimerElapsed(TimeoutTimer timer) 86 | { 87 | if (timer == RaftTimer) 88 | { 89 | var raftOperationResult = Raft.OnTimerElapsed(); 90 | ProcessRaftResult(raftOperationResult, null); 91 | } 92 | } 93 | public event EventHandler OnRaftEvent; 94 | 95 | void ProcessRaftResult(RaftEventResult raftResult, INetworkSocket channel = null) 96 | { 97 | if (raftResult == null) 98 | throw new ArgumentNullException("raftResult"); 99 | if (raftResult.TimerSet) 100 | RaftTimer.SetRandomTimeout(raftResult.TimerValue, raftResult.TimerValue); 101 | if (raftResult.MessageToSend != null) 102 | { 103 | if (raftResult.DoBroadcast) 104 | { 105 | BroadcastMessage(raftResult.MessageToSend); 106 | } 107 | else 108 | { 109 | if (channel == null) 110 | throw new InvalidOperationException("Operation started with no channel"); 111 | SendMessage(channel, raftResult.MessageToSend); 112 | } 113 | } 114 | if (OnRaftEvent != null) 115 | OnRaftEvent(this, raftResult); 116 | } 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /RaftDemo/ViewModels/Actors/ActorViewModel.cs: -------------------------------------------------------------------------------- 1 | using CaliDiagram.ViewModels; 2 | using RaftDemo.Model; 3 | using RaftDemo.NodeSoftware; 4 | using System; 5 | using NetworkModel; 6 | 7 | namespace RaftDemo.ViewModels.Actors 8 | { 9 | public class ActorViewModel: NodeBaseViewModel 10 | { 11 | public ActorViewModel(NodeSoftwareBase nodeSoftware) 12 | { 13 | StartText = "Pause"; 14 | this.NodeSoftware = nodeSoftware; 15 | NodeSoftware.IsStartedChanged += NodeSoftware_IsStartedChanged; 16 | } 17 | 18 | void NodeSoftware_IsStartedChanged(object sender, bool e) 19 | { 20 | IsStarted = e; 21 | } 22 | 23 | private bool _IsStarted; 24 | public bool IsStarted 25 | { 26 | get { return _IsStarted; } 27 | set 28 | { 29 | if (_IsStarted != value) 30 | { 31 | _IsStarted = value; 32 | NotifyOfPropertyChange(() => IsStarted); 33 | } 34 | } 35 | } 36 | 37 | 38 | public NodeSoftwareBase NodeSoftware 39 | { 40 | get; 41 | private set; 42 | } 43 | 44 | public void ButtonPressed(string name) 45 | { 46 | if(name == "startStop") 47 | { 48 | ButtonStartStopClick(); 49 | return; 50 | } 51 | NodeSoftware.RaiseCommandReceived(name); 52 | } 53 | protected override void OnNameChanged(string newName) 54 | { 55 | if(NodeSoftware != null) 56 | NodeSoftware.Id = newName; 57 | } 58 | bool wasCreated = false; 59 | protected override void OnNodeCreated() 60 | { 61 | if (wasCreated) 62 | throw new Exception("NetworkNodeViewModel::OnNodeCreated called twice"); 63 | wasCreated = true; 64 | Console.WriteLine(Name + " Created"); 65 | 66 | foreach (var connection in Connections) 67 | { 68 | // NodeSoftware.RaiseChannelAdded(NodeSoftware.NetworkModel.CreateChannel(connection, this)); 69 | } 70 | NodeSoftware.Start(); 71 | NodeSoftware.OnMessageSent += NodeSoftware_OnMessageSent; 72 | NodeSoftware.Id = Name; 73 | } 74 | 75 | protected override bool OnNodeDeleting() 76 | { 77 | NodeSoftware.OnMessageSent -= NodeSoftware_OnMessageSent; 78 | NodeSoftware.IsStartedChanged -= NodeSoftware_IsStartedChanged; 79 | NodeSoftware.Stop(); 80 | Console.WriteLine(Name + " removed"); 81 | return true; 82 | } 83 | 84 | public void ButtonStartStopClick() 85 | { 86 | if (NodeSoftware.IsStarted) 87 | { 88 | NodeSoftware.Stop(); 89 | StartText = "Resume"; 90 | } 91 | else 92 | { 93 | NodeSoftware.Start(); 94 | StartText = "Pause"; 95 | } 96 | } 97 | 98 | private string _StartText; 99 | public string StartText 100 | { 101 | get { return _StartText; } 102 | set 103 | { 104 | if (_StartText != value) 105 | { 106 | _StartText = value; 107 | NotifyOfPropertyChange(() => StartText); 108 | } 109 | } 110 | } 111 | 112 | 113 | void NodeSoftware_OnMessageSent(object sender, OutboundMessage e) 114 | { 115 | // var connection = e.DestinationChannel.Socket as ConnectionViewModel; 116 | // connection.StartMessageAnimationFrom(this, e.Message); 117 | } 118 | 119 | 120 | protected override void OnConnectionAdded(ConnectionViewModel connection) 121 | { 122 | // INetworkSocket newChannel = NodeSoftware.NetworkModel.CreateChannel(connection, this); 123 | 124 | // NodeSoftware.RaiseChannelAdded(newChannel); 125 | } 126 | protected override void OnConnectionRemoved(ConnectionViewModel connection) 127 | { 128 | NodeSoftware.RaiseSocketDead(connection); 129 | } 130 | 131 | } 132 | } 133 | --------------------------------------------------------------------------------