public AddResourceRequest(ChordNode senderNode, string recId, string recName, string recContent) : base(senderNode, MessageType.AddResourceRequest) { resourceId = recId; resourceName = recName; resourceContent = recContent; resourceAddedSuccessfully = false; }
public static IEnumerable <string> GetAllFilesInSystem(ChordNode node) { var initInstance = ChordServer.Instance(node); SortedSet <string> result = new SortedSet <string>(); foreach (var item in initInstance.GetDb()) { result.Add(item); } initInstance = ChordServer.Instance(initInstance.Successor); while (initInstance.Id != node.Id) { foreach (var item in initInstance.GetDb()) { result.Add(item); } initInstance = ChordServer.Instance(initInstance.Successor); } return(result); }
public static ChordNode GetPredecessor(ChordNode node, int retryCount = RetryCount) { var instance = Instance(node); while (retryCount-- > 0) { try { if (ChordNodeInstance.IsInstanceValid(instance, "GetPredecessor111111111111")) { var retVal = instance.Predecessor; instance.Close(); return(retVal); } } catch (Exception e) { Log(LogLevel.Debug, "Remote Accessor", $"GetPredecessor error: {e.Message}"); } } if (ChordNodeInstance.IsInstanceValid(instance, "GetPredecessor222222222222222") && instance.State != CommunicationState.Closed) { instance.Close(); } return(null); }
public static void CallNotify(ChordNode remoteNode, ChordNode node, int retryCount = RetryCount) { var instance = Instance(remoteNode); while (retryCount-- > 0) { try { if (ChordNodeInstance.IsInstanceValid(instance, "CallNotify1111111111111111111")) { instance.Notify(node); instance.Close(); return; } } catch (Exception e) { Log(LogLevel.Debug, "Remote Invoker", $"CallNotify error: {e.Message}"); } } if (ChordNodeInstance.IsInstanceValid(instance, "CallNotify2222222222222222") && instance.State != CommunicationState.Closed) { instance.Close(); } }
public GetResourceResponse(ChordNode senderNode, string recId, string recName, string recContent, bool recFoundSuccess = true) : base(senderNode, MessageType.GetResourceResponse) { resourceId = recId; resourceName = recName; resourceContent = recContent; resourceFoundSuccessfully = recFoundSuccess; }
/// <summary> /// Get the list of all of the nodes in a Chord ring by starting at seedNode /// and following the successor chain around the ring. There are better ways /// to do this, though churn can almost always screw things up in generating a /// map of what would ideally represent flawlessly the state of the entire /// distributed system at a single given point in time. Realizing that the world /// is not a perfect place can provide great peace at times - you just do the /// best you can and accept imperfection. That's what we do here. /// </summary> /// <param name="seedNode">The node to start collecting the list of nodes in the ring from.</param> /// <returns>A list of nodes in the Chord ring.</returns> private static List <ChordNode> GetNodeList(ChordNode seedNode) { List <ChordNode> nodeList = new List <ChordNode>(); nodeList.Add(seedNode); // don't forget to add the seedNode! // the current node (starting with the seed node's successor) // as we iterate through the ring. ChordNode currNode = ChordServer.GetSuccessor(seedNode); int i = 0; // the number of iterations we have made (so we don't loop infinitely) while (seedNode.ID != currNode.ID && i < MaxNodeLimit) { // get my successor and add it to the nodeList. // eventually, my successor will be the seedNode // or i will hit the maximum node limit, at which // point i just stop currNode = ChordServer.GetSuccessor(currNode); nodeList.Add(currNode); i++; } return(nodeList); }
/// <summary> /// Main program body. /// </summary> /// <param name="args">Arguments. Format assumed is: // ChordTopoMap.exe {-csv | -jpg} <outputFile> <hostname> <port> /// </param> static void Main(string[] args) { if (args != null && args.Length == 4) { // set up the seed node, and generate the internal nodelist and map ChordNode seedNode = new ChordNode(args[2], Convert.ToInt32(args[3])); int[,] hopCountMap; List <ChordNode> nodeList; GenerateMap(seedNode, out nodeList, out hopCountMap); if (args[0].ToLower() == "-csv") { GenerateCsv(hopCountMap, nodeList, args[1]); } else if (args[0].ToLower() == "-jpg") { GenerateImage(hopCountMap, nodeList, args[1]); } } else { // invalid input, print usage PrintUsage(); } }
private static void testLookupPerformance(ChordNode node, ILogger logger) { // initialize random number generator using (var rng = new RNGCryptoServiceProvider()) { // send random key lookup messages for testing the chord network while (true) { // generate a random key byte[] bytes = new byte[20]; rng.GetBytes(bytes); // send a lookup request for the generated key node.LookupKey(new BigInteger(bytes)) .ContinueWith(e => logger.LogInformation( $"Lookup: key '{ HexString.Deserialize(bytes) }' " + $"is managed by node with id '{ HexString.Deserialize(e.Result.NodeId.ToByteArray()) }'")) .Wait(); // sleep for 1 sec Thread.Sleep(1000); } } }
public static void CallSendFile(string file, string path, ChordNode remoteNode, int retryCount = RetryCount) { var instance = Instance(LocalNode); try { instance.SendFile(file, remoteNode, path); } catch (Exception ex) { Log(LogLevel.Debug, "Remote Invoker", $"CallAddFile error: {ex.Message}"); if (retryCount > 0) { CallSendFile(file, path, remoteNode, --retryCount); } else { Log(LogLevel.Debug, "Remote Invoker", $"CallAddValue failed - error: {ex.Message}"); } } finally { instance?.Close(); } }
/// <summary> /// Calls FindSuccessor() remotely, using a default retry value of three. /// </summary> /// <param name="node">The remote node on which to call FindSuccessor().</param> /// <param name="id">The ID to look up.</param> /// <param name="retryCount">The number of times to retry the operation in case of error.</param> /// <returns>The Successor of ID, or NULL in case of error.</returns> public static ChordNode CallFindSuccessor(ChordNode node, ulong id, int retryCount = RetryCount) { var instance = Instance(node); while (retryCount-- > 0) { try { if (ChordNodeInstance.IsInstanceValid(instance, "CallFindSuccessor111111111")) { var retVal = instance.FindSuccessor(id); instance.Close(); return(retVal); } } catch (Exception e) { Log(LogLevel.Debug, "Remote Invoker", $"CallFindSuccessor error: {e.Message}"); } } if (ChordNodeInstance.IsInstanceValid(instance, "CallFindSuccessor222222222222")) { instance.Close(); } return(null); }
public static void Download(ChordNode node, string file, string pathToDownload, bool from) { var fileStream = ChordServer.Instance(node).GetStream(file, from); var request = new FileUploadMessage(); var fileMetadata = new FileMetaData(file); request.Metadata = fileMetadata; request.FileByteStream = fileStream; FileStream outfile = null; outfile = new FileStream(pathToDownload + file, FileMode.Create); const int bufferSize = 65536; // 64K byte[] buffer = new byte[bufferSize]; int bytesRead = request.FileByteStream.Read(buffer, 0, bufferSize); while (bytesRead > 0) { outfile.Write(buffer, 0, bytesRead); bytesRead = request.FileByteStream.Read(buffer, 0, bufferSize); } }
/// <summary> /// Calls FindKey remotely. /// </summary> /// <param name="remoteNode">The remote node on which to call FindKey.</param> /// <param name="key">The key to look up.</param> /// <param name="retryCount">The number of retries to attempt.</param> /// <returns>The value corresponding to the key, or empty string if not found.</returns> public static string CallGetValue(ChordNode remoteNode, ulong key, out ChordNode nodeOut, int retryCount = RetryCount) { var instance = Instance(remoteNode); try { return(instance.GetValue(key, out nodeOut)); } catch (Exception ex) { Log(LogLevel.Debug, "Remote Invoker", $"CallFindKey error: {ex.Message}"); if (retryCount > 0) { return(CallGetValue(remoteNode, key, out nodeOut, --retryCount)); } Log(LogLevel.Debug, "Remote Invoker", $"CallFindKey failed - error: {ex.Message}"); nodeOut = null; return(string.Empty); } finally { instance.Close(); } }
public Message(ChordNode senderNode, MessageType msgType) { this.content = new Dictionary <string, string>(); this.senderID = senderNode.Id; this.senderIpAddress = senderNode.IpAddress; this.senderPort = senderNode.Port; this.messageType = msgType; }
public JoinResponse(ChordNode senderNode, ChordNode succNode, ChordNode predNode) : base(senderNode, MessageType.JoinResponse) { // Successor Info succId = succNode.Id; succIpAddress = succNode.IpAddress; succPort = succNode.Port; // Predecessor Info predId = predNode.Id; predIpAddress = predNode.IpAddress; predPort = predNode.Port; }
public FingerTable(ChordNode node) { Length = 64; Successors = new ChordNode[Length]; StartValues = new ulong[Length]; for (var i = 0; i < Length; ++i) { Successors[i] = node; StartValues[i] = node.Id + (1UL << i); } }
static ChordController() { // determine the local chord endpoint's IP address and port string localIp = IpSettingUtils.GetChordIpv4Address().ToString(); string localPort = IpSettingUtils.GetChordPort().ToString(); // define a function callback for finding bootstrap nodes Func <Task <IChordEndpoint> > bootstrapFunc = () => { return(Task.Run(() => findBootstrapNode())); }; // join the chord network using a bootstrap node node = new ChordNode(sendRequest, localIp, localPort); node.JoinNetwork(bootstrapFunc).Wait(); }
// // Shared functionality // #region Shared Functionality /// <summary> /// Given a starting node for a valid Chord ring, gather the list of all nodes in the ring, /// and get the hopcount map from each node to each other node in the system. /// </summary> /// <param name="seedNode">The starting node in a valid Chord ring.</param> /// <param name="nodeList">The list of Chord nodes in the ring. This list is already sorted.</param> /// <param name="hopcountMap">An N x N matrix of hopcounts where x=y=nodeList.Count.</param> private static void GenerateMap(ChordNode seedNode, out List <ChordNode> nodeList, out int[,] hopcountMap) { // first get the list of all of the nodes in the system nodeList = GetNodeList(seedNode); // set up the hopcountMap to be an N x N matrix where N is the number of nodes in the ring. hopcountMap = new int[nodeList.Count, nodeList.Count]; // now, for each node in the nodelist, measure FindSuccessor() hopcounts to each other node in // the nodelist, and store them in the hopcount map. // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // // Obviously, this can (and should) be multithreaded for any reasonably large system. I've // only made this sample program single-threaded for readability. Translating from a single- // threaded implementation to a multithreaded implementation of the style of the developer's // choice should be considered a reasonable enough task for anyone experimenting more than casually // with NChord (beyond a few thousand nodes). // // sort the nodelist by nodeId (ChordNode implements IComparable and compares on the Node ID value). nodeList.Sort(); // now, go to each node, and have it call FindSuccessor on that nodeId, and hold on to the hopCount // by storing it in the hopCountmap at the appropriate position int y = 0; // the "row" offset in hopcountMap foreach (ChordNode sourceNode in nodeList) { int x = 0; // the "column" offset in hopcountMap // get hopcount from the sourceNode to each destinationNode foreach (ChordNode destinationNode in nodeList) { // CallFindSuccessor connects to sourceNode and calls FindSuccessor for the destination node's // ID. 3 retries (in case of communication failure, etc.) should be more than sufficient. // since we are the initiating node, pass in a value of 0 as the starting hopcount, and store // the resultant hopcount in the appropriate place in the hopcountMap. ChordServer.CallFindSuccessor(sourceNode, destinationNode.ID, 3, 0, out hopcountMap[y, x]); x++; // move to the next column in the row } y++; // move to the next row in the map } // there you go, you have a hopcount map }
public ResourceOwnerResponse(ChordNode senderNode, string recId, ChordNode ownerNode, ChordNode predNode, ChordNode succNode) : base(senderNode, MessageType.OwnerOfIdResponse) { resourceId = recId; // Owner Info ownerId = ownerNode.Id; ownerIpAddress = ownerNode.IpAddress; ownerPort = ownerNode.Port; // Predecessor Info predId = predNode.Id; predIpAddress = predNode.IpAddress; predPort = predNode.Port; // Successor Info succId = succNode.Id; succIpAddress = succNode.IpAddress; succPort = succNode.Port; }
public static void Send(string fileName, string path, ChordNode node) { var key = ChordServer.GetHash(fileName); Stream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); var request = new FileUploadMessage(); var fileMetadata = new FileMetaData(fileName); request.Metadata = fileMetadata; request.FileByteStream = fileStream; var conteinerNode = ChordServer.CallFindContainerKey(node, key); ChordServer.Instance(conteinerNode).AddNewFile(request); }
private ChordNode GetValidNode() { var list = GetNodes(); ChordNode node = null; foreach (var n in list) { if (ChordNodeInstance.IsInstanceValid(ChordServer.Instance(n), "send file")) { node = n; break; } } return(node); }
public static ChordNodeInstanceClient Instance(ChordNode node) { if (node == null) { Log(LogLevel.Error, "Navigation", "Invalid Node (Null Argument)"); return(null); } try { return(new ChordNodeInstanceClient(CreategBinding(), new EndpointAddress($"net.tcp://{node.Host}:{node.Port}/chord"))); } catch (Exception e) { // perhaps instead we should just pass on the error? Log(LogLevel.Error, "Navigation", $"Unable to activate remote server {node.Host}:{node.Port} ({e.Message})."); return(null); } }
public static ChordNode[] GetSuccessorCache(ChordNode node, int retryCount = RetryCount) { var instance = Instance(node); while (retryCount-- > 0) { try { var retVal = instance.SuccessorCache; instance.Close(); return(retVal); } catch (Exception ex) { Log(LogLevel.Debug, "Remote Accessor", $"GetSuccessorCache error: {ex.Message}"); } } instance.Close(); return(null); }
public static void CallReplicationFile(ChordNode remoteNode, string fileName, int retryCount = RetryCount) { try { CallSendFile(fileName, null, remoteNode); } catch (Exception ex) { Log(LogLevel.Debug, "Remote Invoker", $"CallReplicateFile error: {ex.Message}"); if (retryCount > 0) { CallReplicationFile(remoteNode, fileName, --retryCount); } else { Log(LogLevel.Debug, "Remote Invoker", $"CallReplicateFile failed - error: {ex.Message}"); } } }
public static List <ChordNode> FindServiceAddress() { var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); Log(LogLevel.Debug, "Discovery", "Discovering ChordNode Instances"); try { var endpoints = discoveryClient.Find(new FindCriteria(typeof(IChordNodeInstance)) { MaxResults = 4 }).Endpoints; var tmp = endpoints.Select(x => { var inst = Instance(x.Address); ChordNode ret = null; if (ChordNodeInstance.IsInstanceValid(inst, "from FindServiceAddress")) { ret = !inst.LocalNode.Equals(ChordServer.LocalNode) ? inst.LocalNode : null; inst.Close(); } return(ret); }).Where(x => x != null).ToList(); if (endpoints.Count > 0) { Log(LogLevel.Debug, "FindServiceAddress", $"Discovery {tmp.Count} nodes found"); return(tmp); } else { Log(LogLevel.Error, "Discovery", "Nothing found"); } } catch (Exception e) { Log(LogLevel.Error, "Discovery", "Nothing found"); } return(new List <ChordNode>()); }
private static ChordNode initChord(ILogger logger) { // retrieve the node's IP address and port from the local IP configuration var local = new IPEndPoint(IpSettings.GetChordIpv4Address(), IpSettings.GetChordPort()); logger.LogInformation($"Initializing: endpoint={ local.Address }:{ local.Port }, " + $"node id={ HexString.Deserialize(HashingHelper.GetSha1Hash(local)) }"); var netId = IpSettings.GetIpv4NetworkId(); var broadcast = IpSettings.GetIpv4Broadcast(); // connect the chord node to the chord network var node = new ChordNode(local, logger); node.FindBootstrapNode(netId, broadcast) .ContinueWith(x => node.JoinNetwork(x.Result)).Wait(); // write initialization success message to console logger.LogInformation($"Initializing: successful! Going into idle state ..."); return(node); }
public static void Find(string fileName, ChordNode node, string pathToDownload) { var where = Client.Download.Error; var key = ChordServer.GetHash(fileName); var instance = ChordServer.Instance(node); if (instance.ContainKey(key)) { where = Client.Download.DataBase; } else if (instance.ContainInCache(fileName)) { where = Client.Download.Cache; } else { var conteinerNodeInstance = ChordServer.Instance(ChordServer.CallFindContainerKey(node, key)); if (conteinerNodeInstance.ContainKey(key)) { var fileStream = conteinerNodeInstance.GetStream(fileName, false); var request = new FileUploadMessage(); var fileMetadata = new FileMetaData(fileName); request.Metadata = fileMetadata; request.FileByteStream = fileStream; instance.AddCacheFile(request); where = Client.Download.Cache; } } if (Client.Download.Error != where) { Download(node, fileName, pathToDownload, where == Client.Download.Cache); } }
public static ChordNode CallFindContainerKey(ChordNode remoteNode, ulong key, int retryCount = RetryCount) { var instance = Instance(remoteNode); try { return(instance.FindContainerKey(key)); } catch (Exception ex) { Log(LogLevel.Debug, "Remote Invoker", $"CallFindContainerKey error: {ex.Message}"); if (retryCount > 0) { return(CallFindContainerKey(remoteNode, key, --retryCount)); } Log(LogLevel.Debug, "Remote Invoker", $"CallFindContainerKey failed - error: {ex.Message}"); return(null); } finally { instance.Close(); } }
public UpdateSuccNodeRequest(ChordNode senderNode, ChordNode succNode) : base(senderNode, MessageType.UpdateSuccNodeRequest) { succId = succNode.Id; succIpAddress = succNode.IpAddress; succPort = succNode.Port; }
public static void AddFile(string file, string path, ChordNode localNode) { var key = GetHash(file); CallSendFile(file, path, CallFindContainerKey(localNode, key)); }
public static bool SameRing(ChordNode a, ChordNode b) { return(CallFindContainerKey(a, b.Id).Equals(b)); }