示例#1
0
 /// <summary>
 /// Connection string provided by user
 /// </summary>
 /// <param name="replica"></param>
 private void NewStrategyToSetConnectionString(ReplicaInfo replica)
 {
     if (this.connectionStringMap.ContainsKey(replica.StorageAccountName))
     {
         replica.ConnectionString = this.connectionStringMap[replica.StorageAccountName];
     }
     else
     {
         replica.ConnectionString = null;
     }
 }
示例#2
0
        /*
         * Class functions:
         */
        static internal protected CloudTableClient GetTableClientForReplica(ReplicaInfo replica)
        {
            CloudTableClient tableClient = null;

            if (!CloudBlobHelpers.TryCreateCloudTableClient(replica.ConnectionString, out tableClient))
            {
                ReplicatedTableLogger.LogError("No table client created for replica info: {0}", replica);
            }

            return(tableClient);
        }
示例#3
0
        public static View InitFromConfigVer1(string name, ReplicatedTableConfigurationStore configurationStore, Action <ReplicaInfo> SetConnectionString)
        {
            View view = new View(name);

            if (configurationStore != null)
            {
                view.ViewId        = configurationStore.ViewId;
                view.ReadHeadIndex = configurationStore.ReadViewHeadIndex;
                view.RefreshTime   = DateTime.UtcNow;

                foreach (ReplicaInfo replica in configurationStore.ReplicaChain)
                {
                    if (replica == null)
                    {
                        continue;
                    }

                    SetConnectionString(replica);

                    CloudTableClient tableClient = ReplicatedTableConfigurationManager.GetTableClientForReplica(replica);
                    if (tableClient == null)
                    {
                        // All replicas MUST exist or View is not relevant
                        view.Chain.Clear();

                        ReplicatedTableLogger.LogError("ViewName={0} could not load replica ({1})", name, replica);
                        break;
                    }

                    view.Chain.Add(new Tuple <ReplicaInfo, CloudTableClient>(replica, tableClient));
                }

                // If not configured use Tail. Chain must be defined at this point, so don't move this code up!
                view.ReadTailIndex = configurationStore.ReadViewTailIndex;
                if (view.ReadTailIndex < 0)
                {
                    view.ReadTailIndex = view.TailIndex;
                }

                if (!view.IsEmpty)
                {
                    ReplicaInfo head = view.GetReplicaInfo(0);
                    head.Status = ReplicaStatus.WriteOnly;

                    if (view.IsStable)
                    {
                        head.Status = ReplicaStatus.ReadWrite;
                    }
                }
            }

            return(view);
        }
示例#4
0
        internal protected void MoveReplicaToHeadAndSetViewToReadOnly(string viewName, string storageAccountName)
        {
            // Assert (storageAccountName != null)

            int matchIndex = ReplicaChain.FindIndex(r => r.StorageAccountName == storageAccountName);

            if (matchIndex == -1)
            {
                return;
            }

            // - Ensure its status is *None*
            ReplicaInfo candidateReplica = ReplicaChain[matchIndex];

            var oldStatus = candidateReplica.Status;

            candidateReplica.Status = ReplicaStatus.None;

            // First check it will be possible to modify the sequence
            foreach (ReplicaInfo replica in GetCurrentReplicaChain())
            {
                // Change is not possible
                if (replica.Status == ReplicaStatus.WriteOnly)
                {
                    // Restore previous status
                    candidateReplica.Status = oldStatus;

                    var msg = string.Format("View:\'{0}\' : can't set a WriteOnly replica to ReadOnly !!!", viewName);

                    ReplicatedTableLogger.LogError(msg);
                    throw new Exception(msg);
                }
            }

            // Do the change ...

            // - Move it to the front of the chain
            ReplicaChain.RemoveAt(matchIndex);
            ReplicaChain.Insert(0, candidateReplica);

            // Set all active replicas to *ReadOnly*
            foreach (ReplicaInfo replica in GetCurrentReplicaChain())
            {
                replica.Status = ReplicaStatus.ReadOnly;
            }

            // Update view id
            ViewId++;

            // Reset 'ReadViewTailIndex' => user has to set it again
            ResetReadViewTailIndex();
        }
        public void AddReplicaTest()
        {
            Assert.IsTrue(this.repTable.Exists(), "RTable does not exist");

            View v = this.configurationWrapper.GetWriteView();
            int index = v.Chain.Count - 1;
            string accountName = v.GetReplicaInfo(index).StorageAccountName;

            List<ReplicaInfo> replicas = new List<ReplicaInfo>();
            for (int i = 0; i <= index; i++)
            {
                replicas.Add(v.Chain[i].Item1);
            }

            //Just add the last replica again at the head to simulate a new replica addition
            ReplicaInfo newReplica = new ReplicaInfo()
            {
                StorageAccountName = accountName,
            };

            //Add the new replica at the head
            replicas.Insert(0, newReplica);

            int readViewHeadIndex = 1;
            this.UpdateConfiguration(replicas, readViewHeadIndex);

            // validate all state
            Assert.IsFalse(this.configurationWrapper.IsViewStable(), "View = {0}", this.configurationWrapper.GetWriteView().IsStable);
            View readView = this.configurationWrapper.GetReadView();
            View writeView = this.configurationWrapper.GetWriteView();
            long viewIdAfterFirstUpdate = writeView.ViewId;

            // Actually, both read and write views point to the same view
            Assert.IsTrue(readView == writeView);

            int headIndex = 0;
            long readViewHeadViewId = readView.GetReplicaInfo(readViewHeadIndex).ViewInWhichAddedToChain;
            Assert.IsTrue(writeView.GetReplicaInfo(headIndex).ViewInWhichAddedToChain == readViewHeadViewId + 1);

            //Now, make the read and write views the same
            this.UpdateConfiguration(replicas, 0);
            // validate all state
            Assert.IsTrue(this.configurationWrapper.IsViewStable());
            readView = this.configurationWrapper.GetReadView();
            writeView = this.configurationWrapper.GetWriteView();
            Assert.IsTrue(readView == writeView);
            Assert.IsTrue(readView.ViewId == viewIdAfterFirstUpdate + 1);
        }
        private CloudTableClient GetTableClientForReplica(ReplicaInfo replica)
        {
            string connectionString = String.Format(cloudStorageAccountTemplate,
                                                    this.useHttps ? "https" : "http",
                                                    replica.StorageAccountName,
                                                    replica.StorageAccountKey);

            CloudTableClient tableClient = null;

            if (!CloudBlobHelpers.TryCreateCloudTableClient(connectionString, out tableClient))
            {
                ReplicatedTableLogger.LogError("No table client created for replica info: {0}", replica);
            }

            return(tableClient);
        }
示例#7
0
        public override bool Equals(object obj)
        {
            ReplicaInfo other = obj as ReplicaInfo;

            if (other == null)
            {
                return(false);
            }

            if (StorageAccountName != other.StorageAccountName)
            {
                return(false);
            }

            if (ViewInWhichAddedToChain != other.ViewInWhichAddedToChain)
            {
                return(false);
            }

            return(true);
        }
        internal protected void MoveReplicaToHeadAndSetViewToReadOnly(string viewName, string storageAccountName)
        {
            // Assert (storageAccountName != null)

            int matchIndex = ReplicaChain.FindIndex(r => r.StorageAccountName == storageAccountName);

            if (matchIndex == -1)
            {
                return;
            }

            // - Ensure its status is *None*
            ReplicaInfo candidateReplica = ReplicaChain[matchIndex];

            candidateReplica.Status = ReplicaStatus.None;

            // - Move it to the front of the chain
            ReplicaChain.RemoveAt(matchIndex);
            ReplicaChain.Insert(0, candidateReplica);

            // Set all active replicas to *ReadOnly*
            foreach (ReplicaInfo replica in GetCurrentReplicaChain())
            {
                if (replica.Status == ReplicaStatus.WriteOnly)
                {
                    var msg = string.Format("View:\'{0}\' : can't set a WriteOnly replica to ReadOnly !!!", viewName);

                    ReplicatedTableLogger.LogError(msg);
                    throw new Exception(msg);
                }

                replica.Status = ReplicaStatus.ReadOnly;
            }

            // Update view id
            ViewId++;
        }
示例#9
0
        private ReplicatedTableRepairResult RepairTable(string tableName, string storageAccountName, ReplicatedTableConfiguration configuration)
        {
            string viewName = "";

            try
            {
                ReplicatedTableConfiguredTable tableConfig;
                if (!configuration.IsConfiguredTable(tableName, out tableConfig))
                {
                    return(new ReplicatedTableRepairResult(ReplicatedTableRepairCode.NotConfiguredTable, tableName));
                }

                viewName = tableConfig.ViewName;

                List <ReplicaInfo> list = configuration.GetView(viewName).ReplicaChain;
                if (!list.Any() ||
                    list[0].StorageAccountName != storageAccountName)
                {
                    return(new ReplicatedTableRepairResult(ReplicatedTableRepairCode.NotImpactedTable, tableName, viewName, storageAccountName));
                }

                ReplicaInfo head = list[0];
                if (head.Status != ReplicaStatus.WriteOnly)
                {
                    return(new ReplicatedTableRepairResult(ReplicatedTableRepairCode.StableTable, tableName, viewName, storageAccountName));
                }

                int viewIdToRecoverFrom = (int)head.ViewWhenTurnedOff;

                ReplicatedTableLogger.LogInformational("RepairTable={0}, View={1}, StorageAccountName={2}, from viewId={3} ...",
                                                       tableName,
                                                       viewName,
                                                       storageAccountName,
                                                       viewIdToRecoverFrom);
                // Repairing ...
                ReconfigurationStatus status = new ReplicatedTable(tableName, this).RepairTable(viewIdToRecoverFrom, null);

                ReplicatedTableLogger.LogInformational("RepairTable={0}, View={1}, StorageAccountName={2}, from viewId={3} => Status={4}",
                                                       tableName,
                                                       viewName,
                                                       storageAccountName,
                                                       viewIdToRecoverFrom,
                                                       status);

                if (status == ReconfigurationStatus.SUCCESS)
                {
                    return(new ReplicatedTableRepairResult(ReplicatedTableRepairCode.Success, tableName, viewName, storageAccountName));
                }

                // Failure!
                return(new ReplicatedTableRepairResult(ReplicatedTableRepairCode.Error, tableName, viewName, storageAccountName)
                {
                    Status = status,
                });
            }
            catch (Exception ex)
            {
                return(new ReplicatedTableRepairResult(ReplicatedTableRepairCode.Error, tableName, viewName, storageAccountName)
                {
                    Status = ReconfigurationStatus.FAILURE,
                    Message = ex.ToString(),
                });
            }
        }
 /// <summary>
 /// Connection string infered from blob content
 /// </summary>
 /// <param name="replica"></param>
 private void OldStrategyToSetConnectionString(ReplicaInfo replica)
 {
     string connectionString = String.Format(Constants.ShortConnectioStringTemplate, useHttps ? "https" : "http", replica.StorageAccountName, replica.StorageAccountKey);
     replica.ConnectionString = SecureStringHelper.ToSecureString(connectionString);
 }
 /// <summary>
 /// Connection string provided by user
 /// </summary>
 /// <param name="replica"></param>
 private void NewStrategyToSetConnectionString(ReplicaInfo replica)
 {
     if (this.connectionStringMap.ContainsKey(replica.StorageAccountName))
     {
         replica.ConnectionString = this.connectionStringMap[replica.StorageAccountName];
     }
     else
     {
         replica.ConnectionString = null;
     }
 }
        /*
         * Class functions:
         */
        protected internal static CloudTableClient GetTableClientForReplica(ReplicaInfo replica)
        {
            CloudTableClient tableClient = null;
            if (!CloudBlobHelpers.TryCreateCloudTableClient(replica.ConnectionString, out tableClient))
            {
                ReplicatedTableLogger.LogError("No table client created for replica info: {0}", replica);
            }

            return tableClient;
        }
示例#13
0
        /// <summary>
        /// Connection string infered from blob content
        /// </summary>
        /// <param name="replica"></param>
        private void OldStrategyToSetConnectionString(ReplicaInfo replica)
        {
            string connectionString = String.Format(Constants.ShortConnectioStringTemplate, useHttps ? "https" : "http", replica.StorageAccountName, replica.StorageAccountKey);

            replica.ConnectionString = SecureStringHelper.ToSecureString(connectionString);
        }
        private void RefreshReadAndWriteViewsFromBlobs(object arg)
        {
            lock (this)
            {
                this.lastRenewedReadView  = new View();
                this.lastRenewedWriteView = new View();

                DateTime refreshStartTime = DateTime.UtcNow;

                Dictionary <long, List <CloudBlockBlob> > viewResult = new Dictionary <long, List <CloudBlockBlob> >();

                foreach (var blob in this.blobs)
                {
                    ReplicatedTableConfigurationStore configurationStore;
                    if (!CloudBlobHelpers.TryReadBlob <ReplicatedTableConfigurationStore>(blob.Value, out configurationStore))
                    {
                        continue;
                    }

                    if (configurationStore.ViewId <= 0)
                    {
                        ReplicatedTableLogger.LogInformational("ViewId={0} is invalid. Must be >= 1. Skipping this blob {1}.",
                                                               configurationStore.ViewId,
                                                               blob.Value.Uri);
                        continue;
                    }

                    List <CloudBlockBlob> viewBlobs;
                    if (!viewResult.TryGetValue(configurationStore.ViewId, out viewBlobs))
                    {
                        viewBlobs = new List <CloudBlockBlob>();
                        viewResult.Add(configurationStore.ViewId, viewBlobs);
                    }

                    viewBlobs.Add(blob.Value);

                    if (viewBlobs.Count >= this.quorumSize)
                    {
                        this.lastRenewedReadView.ViewId = this.lastRenewedWriteView.ViewId = configurationStore.ViewId;
                        for (int i = 0; i < configurationStore.ReplicaChain.Count; i++)
                        {
                            ReplicaInfo      replica     = configurationStore.ReplicaChain[i];
                            CloudTableClient tableClient = GetTableClientForReplica(replica);
                            if (replica != null && tableClient != null)
                            {
                                //Update the write view always
                                this.lastRenewedWriteView.Chain.Add(new Tuple <ReplicaInfo, CloudTableClient>(replica, tableClient));

                                //Update the read view only for replicas part of the view
                                if (i >= configurationStore.ReadViewHeadIndex)
                                {
                                    this.lastRenewedReadView.Chain.Add(new Tuple <ReplicaInfo, CloudTableClient>(replica, tableClient));
                                }

                                //Note the time when the view was updated
                                this.lastViewRefreshTime = refreshStartTime;

                                this.ConvertXStoreTableMode = configurationStore.ConvertXStoreTableMode;
                            }
                        }

                        this.lastRenewedWriteView.ReadHeadIndex = configurationStore.ReadViewHeadIndex;

                        break;
                    }
                }
            }
        }