/// <summary> /// Get the data node that owns this key /// </summary> /// <remarks> /// Virtual nodes are on a 32 bit ring. Find the location /// of the key's hash and the node that owns it is the first node /// we find from that point upwards. /// </remarks> private static Node GetNodeForKey(string key) { Node returnValue = null; int hashCode = CacheBase.GetConsistentHashCode(key); var keys = CacheBase.RingNodes.Keys; for (int i = 0; i < keys.Count; i++) { if (keys[i] >= hashCode) { if (CacheBase.RingNodes.ContainsKey(keys[i])) { returnValue = CacheBase.RingNodes[keys[i]]; } break; } } if (returnValue == null) { returnValue = CacheBase.RingNodes[keys[0]]; } return(returnValue); }
private Response NodeUnreachable(string hostname, int port) { // MessageType byte (2) // DataLength int // Data byte[] // HostLen int // Host byte[] UTF8 string // Port int byte[] data = null; using (MemoryStream ms = new MemoryStream()) { BinaryWriter w = new BinaryWriter(ms); byte[] hostBytes = CacheBase.WriteHostName(hostname); w.Write(IPAddress.HostToNetworkOrder(hostBytes.Length)); w.Write(hostBytes); w.Write(IPAddress.HostToNetworkOrder(port)); w.Flush(); ms.Flush(); data = ms.ToArray(); } Request request = new Request(Request.Types.NodeUnreachable, data); return(this.SendRequest(this.MasterHostName, this.MasterPort, request)); }
protected Response SendRequest(string hostname, int port, Request request) { IPEndPoint ipep = CacheBase.GetIPEndPoint(hostname, port); if (ipep != null) { using (TcpClient client = new TcpClient()) { try { //client.ReceiveTimeout = 5000; client.SendTimeout = 5000; client.Connect(ipep); using (NetworkStream stream = client.GetStream()) { this.WriteRequest(stream, request); return(this.ReadResponse(stream)); } } catch (SocketException) { } } } return(null); }
/// <summary> /// Removes an item from the Cache. /// </summary> public bool Remove(string key) { Request request = new Request(Request.Types.DeleteObject, key, CacheBase.ToByteArray(key)); var response = base.SendOrQueueNodeRequest(request); if (response == null) { return(false); } return(response.Type == Response.Types.ObjectOk); }
/// <summary> /// Retrieves an item from the cache. /// </summary> public T Get <T>(string key) { T returnValue = default(T); Request request = new Request(Request.Types.GetObject, key, CacheBase.WriteHostName(key)); var response = base.SendOrQueueNodeRequest(request); if (response != null) { if (response.Type == Response.Types.ObjectOk) { returnValue = CacheBase.FromByteArray <T>(response.Data); } } return(returnValue); }
private void ReadConfigBytes(byte[] data) { try { CacheBase.RingNodes = new SortedList <int, Node>(); CacheBase.Nodes = new SortedList <string, Node>(); if (data.Length > 0) { using (MemoryStream ms = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(ms)) { Node node; int numNodes = CacheBase.Read(reader.ReadInt32()); for (int n = 0; n < numNodes; n++) { int hostLen = CacheBase.Read(reader.ReadInt32()); byte[] hostData = new byte[hostLen]; if (reader.Read(hostData, 0, hostLen) != hostLen) { throw new Exception("Invalid GetConfig hostData"); } string hostname = CacheBase.ReadHostName(hostData); int port = CacheBase.Read(reader.ReadInt32()); long maxNumBytes = CacheBase.Read(reader.ReadInt64()); node = new Node( hostname, port, maxNumBytes, (Node.StatusType)reader.ReadByte() ); CacheBase.Nodes[node.Name] = node; bool parseLocations = reader.ReadBoolean(); if (parseLocations) { try { int numLocations = CacheBase.Read(reader.ReadInt32()); int location; for (int i = 0; i < numLocations; i++) { location = CacheBase.Read(reader.ReadInt32()); CacheBase.RingNodes[location] = node; } } catch { string message = "Error reading location Data."; throw new Exception(message); } } } } } } } catch (Exception exo) { string message = string.Format( "Error reading config Data. {0}", exo.Message ); throw new Exception(message); } }
private Response SendNodeRequest(Request request) { Response response = null; // // We'll try 3 times to get our data. // Each node can respond with "im not the right node". // If this happens the node responds with new configuration. // Retry with the new configuration. // Node node = CacheBase.GetNodeForKey(request.Key); for (int i = 0; i < 3; i++) { response = this.SendRequest(node.HostName, node.Port, request); if (response == null) { // // Distination unreachable. // Ask the master if the node is really down. //response = this.NodeUnreachable(node.HostName, node.Port); //if (response == null) // throw new Exception("No response from Master"); //switch (response.Type) //{ // case Response.Types.Accepted: // // // // The node is in fact gone. BOOM! // // // break; // case Response.Types.NodeExists: // // Master says the node is fine. // Wait a tick and try again. // System.Threading.Thread.Sleep(5000); // continue; // default: // this.UnexpectedResponse(response.Type, request.Type); // break; //} } else { switch (response.Type) { case Response.Types.ObjectOk: case Response.Types.ObjectMissing: break; case Response.Types.ReConfigure: this.ReadConfigBytes(response.Data); node = CacheBase.GetNodeForKey(request.Key); continue; case Response.Types.DataNodeNotReady: // // Node isn't ready. // Wait a tick and try again. // System.Threading.Thread.Sleep(50); continue; default: this.UnexpectedResponse(response.Type, request.Type); break; } } break; } return(response); }