public AddResourceRequest(ChordNode senderNode, string recId, string recName, string recContent) : base(senderNode, MessageType.AddResourceRequest)
 {
     resourceId                = recId;
     resourceName              = recName;
     resourceContent           = recContent;
     resourceAddedSuccessfully = false;
 }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
 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;
 }
예제 #6
0
파일: Program.cs 프로젝트: aloklal20/NChord
        /// <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);
        }
예제 #7
0
파일: Program.cs 프로젝트: aloklal20/NChord
        /// <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();
            }
        }
예제 #8
0
        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);
                }
            }
        }
예제 #9
0
        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();
            }
        }
예제 #10
0
        /// <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);
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        /// <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();
            }
        }
예제 #13
0
 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;
 }
예제 #14
0
 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;
 }
예제 #15
0
        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);
            }
        }
예제 #16
0
        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();
        }
예제 #17
0
파일: Program.cs 프로젝트: aloklal20/NChord
        //
        // 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
        }
예제 #18
0
 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;
 }
예제 #19
0
        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);
        }
예제 #20
0
        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);
        }
예제 #21
0
        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);
            }
        }
예제 #22
0
        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);
        }
예제 #23
0
        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}");
                }
            }
        }
예제 #24
0
        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>());
        }
예제 #25
0
        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);
        }
예제 #26
0
        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);
            }
        }
예제 #27
0
        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();
            }
        }
예제 #28
0
 public UpdateSuccNodeRequest(ChordNode senderNode, ChordNode succNode) : base(senderNode, MessageType.UpdateSuccNodeRequest)
 {
     succId        = succNode.Id;
     succIpAddress = succNode.IpAddress;
     succPort      = succNode.Port;
 }
예제 #29
0
        public static void AddFile(string file, string path, ChordNode localNode)
        {
            var key = GetHash(file);

            CallSendFile(file, path, CallFindContainerKey(localNode, key));
        }
예제 #30
0
 public static bool SameRing(ChordNode a, ChordNode b)
 {
     return(CallFindContainerKey(a, b.Id).Equals(b));
 }