/// <summary> /// Delete the entry corresponding to this logical node name from the node mapping table /// as well as the local cache. /// </summary> /// <param name="logicalNodeName"></param> public void DeleteNodeMappingEntry(string logicalNodeName) { lock (this._operationLock) { try { this.RefreshWhenNeeded(); //Update the node mapping table by deleting the entry corresponding to this logical node name CloudTable table = this.TableClient.GetTableReference(this.NodeMappingTableName); TableOperation retrieveOperation = TableOperation.Retrieve <NodeMappingTableEntry>(AzureNaming.AzurePartitionKey, logicalNodeName.ToUpper()); NodeMappingTableEntry entry = null; TableResult retrievedResult = table.Execute(retrieveOperation); if (retrievedResult.Result != null) { entry = (NodeMappingTableEntry)retrievedResult.Result; } if (entry != null) { TableOperation deleteOperation = TableOperation.Delete(entry); table.Execute(deleteOperation); } //Update the cache string physicalEpr = null; if (this._logicalNameToPhysicalEprMapping.TryGetValue(logicalNodeName, out physicalEpr)) { this._logicalNameToPhysicalEprMapping.Remove(logicalNodeName); this._logicalNameToPhysicalInstanceMapping.Remove(logicalNodeName); } if (physicalEpr != null) { this._physicalEprToLogicalNameMapping.Remove(physicalEpr); } } catch (Exception) { //It will get traced in the calling module this.TableClient = null; //If there is any error deleting the entry from the node mapping table //mark the cache for refresh the next time it is accessed this._needRefreshOnNextOperation = true; //Any retry logic should be in the caller throw; } } }
/// <summary> /// refresh the node mapping from Azure storage table for a specific logical node /// this is used for SOA proxy to update the node mapping info /// </summary> /// <param name="logicalNodeName">the node logical name</param> public void RefreshNodeMapping(string logicalNodeName) { lock (this._operationLock) { try { //Retrieve the node entry from node mapping table by the logical node name CloudTable table = this.TableClient.GetTableReference(this.NodeMappingTableName); TableOperation retrieveOperation = TableOperation.Retrieve <NodeMappingTableEntry>(AzureNaming.AzurePartitionKey, logicalNodeName.ToUpper()); NodeMappingTableEntry entry = null; TableResult retrievedResult = table.Execute(retrieveOperation); if (retrievedResult.Result != null) { entry = (NodeMappingTableEntry)retrievedResult.Result; } if (entry != null) { //Update the cache if the epr in the cache is out-of-date string physicalEpr = null; if (this._logicalNameToPhysicalEprMapping.TryGetValue(entry.NodeName, out physicalEpr)) { if (!string.Equals(physicalEpr, entry.EndpointString, StringComparison.OrdinalIgnoreCase)) { this._logicalNameToPhysicalEprMapping[entry.NodeName] = entry.EndpointString; this._logicalNameToPhysicalInstanceMapping[entry.NodeName] = entry.RoleInstanceName; this._physicalEprToLogicalNameMapping[entry.EndpointString] = entry.NodeName; } } else { //insert the node mapping info in the cache this._logicalNameToPhysicalEprMapping[entry.NodeName] = entry.EndpointString; this._logicalNameToPhysicalInstanceMapping[entry.NodeName] = entry.RoleInstanceName; this._physicalEprToLogicalNameMapping[entry.EndpointString] = entry.NodeName; } } } catch (Exception) { //It will get traced in the calling module this.TableClient = null; //Any retry logic should be in the caller throw; } } }
/// <summary> /// THIS IS FOR SCHEDULER INTERNAL USE ONLY! /// The format of endpoint string is: [ip]:[port1]:[port2]:... /// There is no protocol prefix! /// </summary> /// <param name="items"></param> public void UpdateNodeMapping(KeyValuePair <string, string>[] items, Dictionary <string, string> nodeNameToRoleName, Dictionary <string, string> nodeNameToInstanceName) { lock (this._operationLock) { this.RefreshWhenNeeded(); try { CloudTable table = this.TableClient.GetTableReference(this.NodeMappingTableName); foreach (KeyValuePair <string, string> item in items) { string nodeName = item.Key; string endpointString = item.Value; string instanceId = null; nodeNameToInstanceName.TryGetValue(nodeName, out instanceId); // Update the storage first string existingEndpointStr = null; string existingInstanceId = null; if (this._logicalNameToPhysicalEprMapping.TryGetValue(nodeName, out existingEndpointStr)) { if (string.Compare(endpointString, existingEndpointStr, StringComparison.InvariantCultureIgnoreCase) == 0) { if (!this._logicalNameToPhysicalInstanceMapping.TryGetValue(nodeName, out existingInstanceId) || string.Compare(instanceId, existingInstanceId, StringComparison.InvariantCultureIgnoreCase) == 0) { // No need to update continue; } } // Update the storage NodeMappingTableEntry entry = null; try { TableOperation retrieveOperation = TableOperation.Retrieve <NodeMappingTableEntry>(AzureNaming.AzurePartitionKey, nodeName.ToUpper()); TableResult retrievedResult = table.Execute(retrieveOperation); if (retrievedResult.Result != null) { entry = (NodeMappingTableEntry)retrievedResult.Result; } } catch { // Swallow the ResourceNotFound exception, and leave the entry to be null } if (endpointString == null) { // Remove the binding TableOperation deleteOperation = TableOperation.Delete(entry); table.Execute(deleteOperation); } else { entry.EndpointString = endpointString; entry.RoleInstanceName = instanceId; TableOperation updateOperation = TableOperation.Replace(entry); table.Execute(updateOperation); } } else { if (endpointString == null) { // We don't save a null phyical address continue; } // Add to the storage table Debug.Assert(nodeNameToRoleName.ContainsKey(nodeName)); NodeMappingTableEntry entry = new NodeMappingTableEntry(nodeName.ToUpper(), endpointString, nodeNameToRoleName[nodeName], nodeNameToInstanceName[nodeName]); TableOperation insertOperation = TableOperation.Insert(entry); table.Execute(insertOperation); } } // Now update the cache at last foreach (KeyValuePair <string, string> item in items) { string originalEndpointString; if (this._logicalNameToPhysicalEprMapping.TryGetValue(item.Key, out originalEndpointString)) { this._physicalEprToLogicalNameMapping.Remove(originalEndpointString); } if (item.Value == null) { // This means remove the binding this._logicalNameToPhysicalEprMapping.Remove(item.Key); this._logicalNameToPhysicalInstanceMapping.Remove(item.Key); } else { // This means update the binding this._logicalNameToPhysicalEprMapping[item.Key] = item.Value; this._physicalEprToLogicalNameMapping[item.Value] = item.Key; string instanceId = null; if (nodeNameToRoleName.TryGetValue(item.Key, out instanceId)) { this._logicalNameToPhysicalInstanceMapping[item.Key] = instanceId; } } } } catch (Exception) { this.TableClient = null; this._needRefreshOnNextOperation = true; throw; } } }