public void respondIfNewNode(String machineName, String sellerName, Uri machine) { // Clear the cache because the system changed -> the data changed cache.clear(); //Barrier - Create, Enter, BLOCK -> Leave when Balancing ends var barrier = AirlineReplicationModule.Instance.barrier(); // Get the cuurent snapshot of the system - including the new machine that came up! //not included the sellers that it holds. Dictionary <string, ZNodesDataStructures.MachineNode> machines = AirlineReplicationModule.Instance.Machines; // in the ZK tree: If a machine holds a seller that has return to live - drop it! foreach (string smachine in machines.Keys) { if (!smachine.Equals(machineName)) { machines[smachine].primaryOf.Remove(sellerName); machines[smachine].backsUp.Remove(sellerName); } } // this is the oldest legal view of the tree. necessary to enable sellers transfers Dictionary <string, ZNodesDataStructures.MachineNode> machinesOldVersion = copyMachines(machines); // in the local data: If a this machine holds an old version of the seller - drop it!! if (!machineName.Equals(myName)) { primaries.RemoveAll(delegate(Seller candidate) { return(candidate.name.Equals(sellerName)); }); backups.RemoveAll(delegate(Seller candidate) { return(candidate.name.Equals(sellerName)); }); } // the new machine holds the new seller // If there is only a single machine there is no need to backup the seller and load balancing if (machines.Count == 1) { try { ServiceEndpoint sellerSearchEndPoint = new ServiceEndpoint(ContractDescription.GetContract( typeof(IAirSellerRegisteration)), new WebHttpBinding(), new EndpointAddress (mysearchServerAddress)); using (WebChannelFactory <IAirSellerRegisteration> cf = new WebChannelFactory <IAirSellerRegisteration>(sellerSearchEndPoint)) { IAirSellerRegisteration registerChannel = cf.CreateChannel(); //Register the channel in the server registerChannel.RegisterSeller(new Uri(myAddress), clusterName); } } catch (ProtocolException e) { Console.WriteLine("Bad Protocol: " + e.Message); } catch (Exception e) { if (e.InnerException is WebException) { HttpWebResponse resp = (HttpWebResponse)((WebException)e.InnerException).Response; Console.WriteLine("Failed, {0}", resp.StatusDescription); } else { Console.WriteLine("Advertisement connection kicked the bucket, quitting because:"); Console.WriteLine(e.Message.ToString()); } return; } } else { // if there are 2 machines - it means that before the current machine has joined there were no backups! if (machines.Count == 2) { // get the oldest machine string oldMachine = machines.Keys.Where(delegate(string str) { return(!str.Equals(machineName)); }).First(); // backup all the sellers in the old machine foreach (string sell in machines[oldMachine].primaryOf) { machines[machineName].backsUp.Add(sell); if (machineName.Equals(myName)) { ServiceEndpoint endPoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(ISellerClusterService)), new BasicHttpBinding(), new EndpointAddress(machines[oldMachine].uri)); using (ChannelFactory <ISellerClusterService> httpFactory = new ChannelFactory <ISellerClusterService>(endPoint)) { ISellerClusterService sellerCluster = httpFactory.CreateChannel(); try { Seller sellerToBackup = sellerCluster.sendPrimarySeller(sell); if (sellerToBackup == null) { sellerToBackup = sellerCluster.sendBackupSeller(sellerName); } backups.Add(sellerToBackup); } catch (FaultException fe) { Console.WriteLine("Failure in getting seller. Because: " + fe.Message); return; } } } } } // find a deterministic victim to hold the backup of the new seller string victim = (from p in machines where !p.Key.Equals(machineName) orderby p.Value.primaryOf.Count ascending, p.Key ascending select p.Key).First(); // if the victim is this machine - follow the command and ask a clone from the new machine that owns the primary replica if (victim.Equals(myName)) { Uri uri = machine; ServiceEndpoint endPoint = new ServiceEndpoint( ContractDescription.GetContract(typeof(ISellerClusterService)), new BasicHttpBinding(), new EndpointAddress(machines[machineName].uri)); using (ChannelFactory <ISellerClusterService> httpFactory = new ChannelFactory <ISellerClusterService>(endPoint)) { ISellerClusterService sellerCluster = httpFactory.CreateChannel(); try { Seller sellerToBackup = sellerCluster.sendPrimarySeller(sellerName); if (sellerToBackup == null) { sellerToBackup = sellerCluster.sendBackupSeller(sellerName); } backups.Add(sellerToBackup); } catch (FaultException fe) { Console.WriteLine("Failure in getting seller. Because: " + fe.Message); return; } } } // update it in the ZK tree machines[victim].backsUp.Add(sellerName); } // execute a deterministic load-balancing algorithm if (machines.Keys.Count > 1) { Console.WriteLine("\t** BALANCING ALGORITHM STARTED **"); balanceTheTreeAfterJoined(machines, machinesOldVersion, machineName, machine); // this lock makes sure that no search server will serviced while sellers are removed from the machine. Console.WriteLine("\t** BALANCING ALGORITHM FINISHED **"); } //// barrier: in order to prevent losing replicas at same time that other machines asks for them barrier.Leave(); // update the ZK server!! AirlineReplicationModule.Instance.updateMachineData(machines); // update the primaries and backups lists - now we can remove the not needed replicas primaries.RemoveAll(delegate(Seller p) { return(!machines[myName].primaryOf.Contains(p.name)); }); backups.RemoveAll(delegate(Seller p) { return(!machines[myName].backsUp.Contains(p.name)); }); // print replicas status print(machines); }
public void respondIfSomeoneLeft(List <String> sellersWhoLostPrimary, List <String> sellersWhoLostBackup) { var barrier = AirlineReplicationModule.Instance.barrier(); // If this machine is a leader: register as a delegate if (!isLeader && checkIfLeader()) { isLeader = true; try { ServiceEndpoint sellerSearchEndPoint = new ServiceEndpoint(ContractDescription.GetContract( typeof(IAirSellerRegisteration)), new WebHttpBinding(), new EndpointAddress (mysearchServerAddress)); using (WebChannelFactory <IAirSellerRegisteration> cf = new WebChannelFactory <IAirSellerRegisteration>(sellerSearchEndPoint)) { IAirSellerRegisteration registerChannel = cf.CreateChannel(); //Register the channel in the server registerChannel.RegisterSeller(new Uri(myAddress), clusterName); } } catch (ProtocolException e) { Console.WriteLine("Bad Protocol: " + e.Message); } catch (Exception e) { if (e.InnerException is WebException) { HttpWebResponse resp = (HttpWebResponse)((WebException)e.InnerException).Response; Console.WriteLine("Failed, {0}", resp.StatusDescription); } else { Console.WriteLine("Advertisement connection kicked the bucket, quitting because:"); Console.WriteLine(e.Message.ToString()); } return; } } // get the updated snapshot Dictionary <string, ZNodesDataStructures.MachineNode> machines = AirlineReplicationModule.Instance.Machines; Dictionary <string, ZNodesDataStructures.MachineNode> machinesOldVersion = copyMachines(machines); Console.WriteLine("\t** BALANCING ALGORITHM STARTED **"); // execute a deterministic load-balancing algorithm - and also fill the machines with backup nodes balanceTheTreeAfterLeft(machines, machinesOldVersion, sellersWhoLostBackup, sellersWhoLostPrimary); Console.WriteLine("\t** BALANCING ALGORITHM FINISHED **"); //Barrier barrier.Leave(); AirlineReplicationModule.Instance.updateMachineData(machines); primaries.RemoveAll(delegate(Seller s) { return(!machines[myName].primaryOf.Contains(s.name)); }); backups.RemoveAll(delegate(Seller s) { return(!machines[myName].backsUp.Contains(s.name)); }); print(machines); }