/// <summary> /// Methiod to be replaced!!! /// </summary> /// <param name="remoteAddress">The address of a remote node to connect to.</param> /// <returns>A network connected to that node.</returns> internal NetworkBase ConnectTo(NodeAddress remoteAddress) { var existing = connectedNetworks.FirstOrDefault(n => n.CanCreate(remoteAddress)); if (existing != null) { existing.Connect(remoteAddress); return(existing); } foreach (var reg in availableNetworks) { NetworkBase result; if (reg.CanCreate(remoteAddress)) { result = reg.CreateNetwork(); result.Connect(remoteAddress); if (result != null) { connectedNetworks.Add(result); return(result); } } } return(null); }
/// <summary>Finds the <see cref="Node"/> for the given <see cref="NodeAddress"/>.</summary> /// <param name="address">The <see cref="NodeAddress"/> to find.</param> /// <returns>The found <see cref="Node"/>.</returns> public INode FindOrCreate(NodeAddress address) { var found = FindOrDefault(address); if (found == null) { found = Create(address); connectedNodes.Add(found); } return(found); }
/// <summary>Detach this node from its parent and advises each child to connect to the /// parent individually via <see cref="AdviseConnect"/>.</summary> public override void Disconnect() { NodeAddress parent = Address.Parent; DetachFromParent(); // Take a copy of the children so they disconnect at will foreach (var child in Children.ToArray()) { var childNode = Network.FindOrCreate(child); childNode.AdviseConnect(parent); } }
/// <summary>The advise connect.</summary> /// <param name="newParent">The parent.</param> public override void AdviseConnect(NodeAddress newParent) { if (HasParent && !Address.Parent.Matches(newParent)) { DetachFromParent(); } var parentNode = Network.FindOrCreate(newParent); var actualParentAddress = parentNode.Connect(Address); if (actualParentAddress.Matches(newParent)) { Address.Parent = newParent; OnIsConnectedChanged(); } }
/// <summary> /// Sends some data to the entire network. /// </summary> /// <param name="network">Where to send the data.</param> /// <param name="type">Type of data to send.</param> /// <param name="data">Untyped data to send.</param> /// <param name="from">Where this data originates from.</param> public void SendToNetwork(INetwork network, string type, byte[] data, NodeAddress from) { var recipient = network.FindOrDefault(Address.Parent); if (recipient != null && recipient.Address.Matches(from) == false) { recipient.Send(type, data, Address); } foreach (var x in Children) { if (x.Matches(from) == false) { recipient = network.FindOrDefault(x); recipient.Send(type, data, Address); } } }
/// <summary>Connects with a new node, by determining which is the parent.</summary> /// <remarks>Delegates to the <see cref="NodeWithoutContract.ElectionStrategy"/> to confirm if we should be the parent of the node.</remarks> /// <param name="newNode">The new node.</param> /// <returns>The <see cref="NodeAddress"/>.</returns> public override NodeAddress Connect(NodeAddress newNode) { if (Address.AsString == newNode.AsString) { throw new InvalidOperationException(Address + " is my local address - Can't connect to " + newNode); } var parent = this as INode; var child = Network.FindOrCreate(newNode); ElectionStrategy.DetermineParent(ref parent, ref child); if (parent == this) { ConnectChild(child); return(Address); } else { child.AdviseConnect(Address); return(null); } }
/// <summary> /// Initializes a new instance of the <see cref="Node"/> class.</summary> /// <remarks>You can't call this, instead use <see cref="INetwork.FindOrCreate"/> which will create and track nodes for you </remarks> /// <param name="newAddress">The new address.</param> /// <param name="locator">The locator used to connect to other nodes.</param> internal Node(NodeAddress newAddress, INetwork locator) { Address = newAddress; Network = locator; ElectionStrategy = new FirstComeFirstElectedStrategy(); }
/// <summary>Registers a child node.</summary> /// <param name="address">The address.</param> protected void AddChild(NodeAddress address) { Children.Add(address); }
/// <summary> /// Determines if this network can connect to a given <see cref="NodeAddress"/> /// </summary> /// <param name="remoteAddress">The remote address that we should detect if we can connect to.</param> /// <returns>True if we know how to connect to that type of address.</returns> internal virtual bool CanCreate(NodeAddress remoteAddress) { return(remoteAddress.AsString.StartsWith(SchemaName)); }
/// <summary>Sends data across the network.</summary> /// <param name="type"><see cref="Type"/> that the data should be deserialized to.</param> /// <param name="data">The data.</param> /// <param name="from">Where not to send data back to.</param> public abstract void Send(string type, byte[] data, NodeAddress from);
/// <summary>Advises a child node to disconnect from its parent.</summary> /// <param name="address">The address.</param> public abstract void ChildDisconnect(NodeAddress address);
/// <summary>Send advise to another node of who it should connect to.</summary> /// <remarks>When a parent has children and the parent is closing down, we will advise each child to connect to the /// grandparent instead. (See <see cref="INodeContract.Connect"/> for a quick description of how the grandparent will delegate /// connection to other nodes instead.</remarks> /// <param name="newParent">The parent.</param> public abstract void AdviseConnect(NodeAddress newParent);
/// <summary>Ask the node given in the <paramref name="newNode"/> parameter who we should connect to.</summary> /// <remarks>The <see cref="Node.ElectionStrategy"/> is used to decide who we should actually connect to as a child. /// This could mean that this node actually becomes the child of a completely different node, for example when the /// node we asked is already full and delegates us to its child. Alternatively it could decide that we shouldn't be anyone's child, /// so it will attempt to connect to us by calling our <see cref="INodeContract.Connect"/> instead.</remarks> /// <param name="newNode">The node we think we want to connect to.</param> /// <returns>The node we actually did connect to.</returns> public abstract NodeAddress Connect(NodeAddress newNode);
/// <summary>Determines if this <see cref="Node"/> has the given child.</summary> /// <param name="address">The address.</param> /// <returns>The <see cref="bool"/>.</returns> public bool HasChild(NodeAddress address) { return(Children.Any(x => x.Matches(address))); }
/// <summary>Finds the <see cref="Node"/> for the given <see cref="NodeAddress"/>.</summary> /// <param name="address">The <see cref="NodeAddress"/> to find.</param> /// <returns>The found <see cref="Node"/> or null.</returns> public INode FindOrDefault(NodeAddress address) { var found = (from x in connectedNodes where x.Address.Matches(address) select x).FirstOrDefault(); return(found); }
/// <summary>Add a node to the network.</summary> /// <param name="child">The child.</param> public virtual void Connect(NodeAddress child) { Local.Connect(child); }
/// <summary>Disconnect the given child.</summary> /// <param name="address">The address.</param> public override void ChildDisconnect(NodeAddress address) { Contract.Assert(Children.Any(x => x.Matches(address))); Children.RemoveAll(x => x.Matches(address)); }
/// <summary>Creates nodes representing other nodes.</summary> /// <param name="address">The address.</param> /// <returns>The <see cref="INode"/>.</returns> protected abstract INode Create(NodeAddress address);
/// <summary>Sends data across the network.</summary> /// <param name="type"><see cref="Type"/> to deserialize data back to.</param> /// <param name="data">The data.</param> /// <param name="from">Where the data came from.</param> public override void Send(string type, byte[] data, NodeAddress from) { Network.OnReceived(type, data); SendToNetwork(Network, type, data, from); }