예제 #1
0
        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);
        }
예제 #2
0
        private void balanceTheTreeAfterLeft(Dictionary <string, ZNodesDataStructures.MachineNode> machines, Dictionary <string, ZNodesDataStructures.MachineNode> machinesOldView, List <string> backupsToAssign, List <string> primariesToAssign)
        {
            // calculate the average number of sellers (separately primaries and backups)
            // that each machine has to hold approximately in order to keep load balancing
            int averageP = 0, averageB = 0;

            foreach (string mac in machines.Keys)
            {
                averageP += machines[mac].primaryOf.Count;
                averageB += machines[mac].backsUp.Count;
            }
            averageP = Convert.ToInt32(Math.Ceiling((Convert.ToDecimal(averageP) + primariesToAssign.Count) / machines.Count));
            averageB = Convert.ToInt32(Math.Ceiling((Convert.ToDecimal(averageB) + backupsToAssign.Count) / machines.Count));

            // we want a deterministic list of the machines order by their availability
            // so we reverese the list
            List <string> reverseBusy = getTheMostBusyMachineOrderByPrimaries(machines);

            reverseBusy.Reverse();
            primariesToAssign.Sort();
            List <string> backupsThatShouldBeMoved = new List <string>();

            foreach (string lightMachine in reverseBusy)
            {
                // no primaries to assign
                if (primariesToAssign.Count == 0)
                {
                    break;
                }

                // move primaries to the light machine
                while (machines[lightMachine].primaryOf.Count < averageP)
                {
                    if (primariesToAssign.Count == 0)
                    {
                        break;
                    }

                    // do the transfer
                    string primaryToTransfer = primariesToAssign.First();
                    machines[lightMachine].primaryOf.Add(primaryToTransfer);
                    if (machines[lightMachine].backsUp.Contains(primaryToTransfer))
                    {
                        machines[lightMachine].backsUp.Remove(primaryToTransfer);
                        backupsToAssign.Add(primaryToTransfer);
                        backupsThatShouldBeMoved.Add(primaryToTransfer);
                    }

                    // ask for the seller from another machine
                    if (lightMachine.Equals(myName))
                    {
                        Uri             uri      = FindBackupOfSeller(primaryToTransfer, machinesOldView);
                        ServiceEndpoint endPoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(ISellerClusterService)), new BasicHttpBinding(), new EndpointAddress(uri));
                        using (ChannelFactory <ISellerClusterService> httpFactory = new ChannelFactory <ISellerClusterService>(endPoint))
                        {
                            try
                            {
                                ISellerClusterService sellerCluster = httpFactory.CreateChannel();
                                Seller sellerToPrimary = sellerCluster.sendBackupSeller(primaryToTransfer);
                                primaries.Add(sellerToPrimary);
                            }
                            catch (FaultException fe)
                            {
                                Console.WriteLine("Failure in getting seller. Because: " + fe.Message);
                                return;
                            }
                        }
                    }
                    primariesToAssign.Remove(primaryToTransfer);
                }
            }

            // this phase load balance the backup
            List <string> idles       = getTheMostBusyMachineOrderByBackups(machines);

            idles.Reverse();
            backupsToAssign.Sort();

            // balance the machines order by backups
            foreach (string lightMachine in idles)
            {
                if (backupsToAssign.Count == 0)
                {
                    break;
                }

                // move until machine get to the average amount of backups
                while (machines[lightMachine].backsUp.Count < averageB)
                {
                    if (backupsToAssign.Except(machines[lightMachine].primaryOf).Count() == 0)
                    {
                        break;
                    }
                    List <string> bs = backupsToAssign.Except(machines[lightMachine].primaryOf).ToList();
                    bs.Sort();
                    string backupToTransfer = bs.First();
                    machines[lightMachine].backsUp.Add(backupToTransfer);

                    // we distinct between 2 cases: backups that have been removed from another machine, and backups that
                    // came from the dropped machine
                    if (lightMachine.Equals(myName))
                    {
                        if (backupsThatShouldBeMoved.Contains(backupToTransfer))
                        {
                            Uri             uri      = FindBackupOfSeller(backupToTransfer, machinesOldView);
                            ServiceEndpoint endPoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(ISellerClusterService)), new BasicHttpBinding(), new EndpointAddress(uri));
                            using (ChannelFactory <ISellerClusterService> httpFactory = new ChannelFactory <ISellerClusterService>(endPoint))
                            {
                                try
                                {
                                    Seller sellerToPrimary;
                                    ISellerClusterService sellerCluster = httpFactory.CreateChannel();
                                    sellerToPrimary = sellerCluster.sendBackupSeller(backupToTransfer);
                                    backups.Add(sellerToPrimary);
                                }
                                catch (FaultException fe)
                                {
                                    Console.WriteLine("Failure in getting seller. Because: " + fe.Message);
                                    return;
                                }
                            }
                        }
                        else
                        {
                            Uri             uri      = FindPrimaryOfSeller(backupToTransfer, machinesOldView);
                            ServiceEndpoint endPoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(ISellerClusterService)), new BasicHttpBinding(), new EndpointAddress(uri));
                            using (ChannelFactory <ISellerClusterService> httpFactory = new ChannelFactory <ISellerClusterService>(endPoint))
                            {
                                try
                                {
                                    Seller sellerToPrimary;
                                    ISellerClusterService sellerCluster = httpFactory.CreateChannel();
                                    sellerToPrimary = sellerCluster.sendPrimarySeller(backupToTransfer);
                                    backups.Add(sellerToPrimary);
                                }
                                catch (FaultException fe)
                                {
                                    Console.WriteLine("Failure in getting seller. Because: " + fe.Message);
                                    return;
                                }
                            }
                        }
                    }
                    backupsToAssign.Remove(backupToTransfer);
                }
            }
        }