예제 #1
0
        public void TestShardMapManagerExceptionSerializability()
        {
            var errorCategory = ShardManagementErrorCategory.RangeShardMap;
            var errorCode     = ShardManagementErrorCode.ShardMapDoesNotExist;

            ShardManagementException ex = new ShardManagementException(errorCategory, errorCode, "Testing");
            string exceptionToString    = ex.ToString();

            // Serialize and de-serialize with a BinaryFormatter
            BinaryFormatter bf = new BinaryFormatter();

            using (MemoryStream ms = new MemoryStream())
            {
                // Serialize
                bf.Serialize(ms, ex);

                // Deserialize
                ms.Seek(0, 0);
                ex = (ShardManagementException)bf.Deserialize(ms);
            }

            // Validate
            Assert.AreEqual(ex.ErrorCode, errorCode, "ErrorCode");
            Assert.AreEqual(ex.ErrorCategory, errorCategory, "ErrorCategory");
            Assert.AreEqual(exceptionToString, ex.ToString(), "ToString()");
        }
예제 #2
0
        public void TestShardMapManagerExceptionSerializability()
        {
            var errorCategory = ShardManagementErrorCategory.RangeShardMap;
            var errorCode     = ShardManagementErrorCode.ShardMapDoesNotExist;

            ShardManagementException ex           = new ShardManagementException(errorCategory, errorCode, "Testing");
            ShardManagementException deserialized = CommonTestUtils.SerializeDeserialize(ex);

            // Validate
            Assert.AreEqual(ex.ErrorCode, deserialized.ErrorCode, "ErrorCode");
            Assert.AreEqual(ex.ErrorCategory, deserialized.ErrorCategory, "ErrorCategory");
            Assert.AreEqual(ex.ToString(), deserialized.ToString(), "ToString()");
        }
        public void CreateShardMapManager_NoOverwrite()
        {
            ShardMapManagerFactory.CreateSqlShardMapManager(
                Globals.ShardMapManagerConnectionString,
                ShardMapManagerCreateMode.ReplaceExisting);

            ShardManagementException smme = AssertExtensions.AssertThrows <ShardManagementException>(() =>
                                                                                                     ShardMapManagerFactory.CreateSqlShardMapManager(
                                                                                                         Globals.ShardMapManagerConnectionString,
                                                                                                         ShardMapManagerCreateMode.KeepExisting));

            Assert.AreEqual(ShardManagementErrorCategory.ShardMapManagerFactory, smme.ErrorCategory);
            Assert.AreEqual(ShardManagementErrorCode.ShardMapManagerStoreAlreadyExists, smme.ErrorCode);
        }
예제 #4
0
        private void VerifyGlobalStore(ShardMapManager smm, Version targetVersion)
        {
            // Verify upgrade
            Assert.AreEqual(
                targetVersion,
                GetGlobalStoreVersion());

            string shardMapName = string.Format("MyShardMap_{0}", Guid.NewGuid());

            if (targetVersion != null && targetVersion < new Version(1, 1))
            {
                ShardManagementException sme = AssertExtensions.AssertThrows <ShardManagementException>(
                    () => smm.CreateListShardMap <int>(shardMapName));
                Assert.AreEqual(ShardManagementErrorCode.GlobalStoreVersionMismatch, sme.ErrorCode);
            }
            else
            {
                // Below call should succeed as latest supported major version of library matches major version of deployed store.
                ShardMap sm = smm.CreateListShardMap <int>(shardMapName);
                Assert.IsNotNull(sm);
            }
        }
예제 #5
0
        public void BasicScenarioRangeShardMaps()
        {
            bool   success           = true;
            string rangeShardMapName = "MultiTenantShardMap";

            try
            {
                #region DeployShardMapManager

                // Deploy shard map manager.
                ShardMapManagerFactory.CreateSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerCreateMode.ReplaceExisting);

                #endregion DeployShardMapManager

                #region GetShardMapManager

                // Obtain shard map manager.
                ShardMapManager shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                #endregion GetShardMapManager

                #region CreateRangeShardMap

                // Create a single user per-tenant shard map.
                RangeShardMap <int> multiTenantShardMap = shardMapManager.CreateRangeShardMap <int>(rangeShardMapName);

                #endregion CreateRangeShardMap

                #region CreateShardAndRangeMapping

                for (int i = 0; i < ScenarioTests.s_multiTenantDBs.Length; i++)
                {
                    // Create the shard.
                    Shard s = multiTenantShardMap.CreateShard(
                        new ShardLocation(
                            Globals.ShardMapManagerTestsDatasourceName,
                            ScenarioTests.s_multiTenantDBs[i]));

                    // Create the mapping.
                    RangeMapping <int> r = multiTenantShardMap.CreateRangeMapping(
                        new Range <int>(i * 10, (i + 1) * 10),
                        s);
                }

                #endregion CreateShardAndRangeMapping

                #region UpdateMapping

                // Let's add [50, 60) and map it to same shard as 23 i.e. MultiTenantDB3.

                RangeMapping <int> mappingFor23 = multiTenantShardMap.GetMappingForKey(23);

                RangeMapping <int> mappingFor50To60 = multiTenantShardMap.CreateRangeMapping(
                    new Range <int>(50, 60),
                    mappingFor23.Shard);

                Assert.IsTrue(mappingFor23.Shard.Location.Equals(mappingFor50To60.Shard.Location));

                // Move [10, 20) from MultiTenantDB2 to MultiTenantDB1
                RangeMapping <int> mappingToUpdate = multiTenantShardMap.GetMappingForKey(10);
                RangeMapping <int> mappingFor5     = multiTenantShardMap.GetMappingForKey(5);
                bool updateFailed = false;

                // Try updating that shard in the mapping without taking it offline first.
                try
                {
                    multiTenantShardMap.UpdateMapping(
                        mappingToUpdate,
                        new RangeMappingUpdate
                    {
                        Shard = mappingFor5.Shard
                    });
                }
                catch (ShardManagementException smme)
                {
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingIsNotOffline);
                    updateFailed = true;
                }

                Trace.Assert(updateFailed);

                // Mark mapping offline, update shard location.
                RangeMapping <int> newMappingFor10To20Offline = MarkMappingOfflineAndUpdateShard <int>(
                    multiTenantShardMap, mappingToUpdate, mappingFor5.Shard);

                // Verify that update succeeded.
                Assert.IsTrue(newMappingFor10To20Offline.Shard.Location.Equals(mappingFor5.Shard.Location));
                Assert.IsTrue(newMappingFor10To20Offline.Status == MappingStatus.Offline);

                // Bring the mapping back online.
                RangeMapping <int> newMappingFor10To20Online = multiTenantShardMap.UpdateMapping(
                    newMappingFor10To20Offline,
                    new RangeMappingUpdate
                {
                    Status = MappingStatus.Online,
                });

                // Verify that update succeeded.
                Assert.IsTrue(newMappingFor10To20Online.Status == MappingStatus.Online);

                #endregion UpdateMapping

                #region DeleteMapping

                // Find mapping for [0, 10).
                RangeMapping <int> mappingToDelete = multiTenantShardMap.GetMappingForKey(5);
                bool operationFailed = false;

                // Try to delete mapping while it is online, the delete should fail.
                try
                {
                    multiTenantShardMap.DeleteMapping(mappingToDelete);
                }
                catch (ShardManagementException smme)
                {
                    operationFailed = true;
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingIsNotOffline);
                }

                Trace.Assert(operationFailed);

                // The mapping must be made offline first before it can be deleted.
                RangeMappingUpdate ru = new RangeMappingUpdate();
                ru.Status = MappingStatus.Offline;

                mappingToDelete = multiTenantShardMap.UpdateMapping(mappingToDelete, ru);
                Trace.Assert(mappingToDelete.Status == MappingStatus.Offline);

                multiTenantShardMap.DeleteMapping(mappingToDelete);

                // Verify that delete succeeded.
                try
                {
                    RangeMapping <int> deletedMapping = multiTenantShardMap.GetMappingForKey(5);
                }
                catch (ShardManagementException smme)
                {
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingNotFoundForKey);
                }

                #endregion DeleteMapping

                #region OpenConnection without Validation

                using (SqlConnection conn = multiTenantShardMap.OpenConnectionForKey(
                           20,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None))
                {
                }

                #endregion OpenConnection without Validation

                #region OpenConnection with Validation

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                bool validationFailed = false;
                try
                {
                    using (SqlConnection conn = multiTenantShardMap.OpenConnection(
                               mappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate))
                    {
                    }
                }
                catch (ShardManagementException smme)
                {
                    validationFailed = true;
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                }

                Assert.AreEqual(validationFailed, true);

                #endregion OpenConnection with Validation

                #region OpenConnection without Validation and Empty Cache

                // Obtain new shard map manager instance
                ShardMapManager newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the Range Shard Map
                RangeShardMap <int> newMultiTenantShardMap = newShardMapManager.GetRangeShardMap <int>(rangeShardMapName);

                using (SqlConnection conn = newMultiTenantShardMap.OpenConnectionForKey(
                           20,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None))
                {
                }

                #endregion

                #region OpenConnection with Validation and Empty Cache

                // Obtain new shard map manager instance
                newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the Range Shard Map
                newMultiTenantShardMap = newShardMapManager.GetRangeShardMap <int>(rangeShardMapName);

                // Create a new mapping
                RangeMapping <int> newMappingToDelete = newMultiTenantShardMap.CreateRangeMapping(
                    new Range <int>(70, 80),
                    newMultiTenantShardMap.GetMappingForKey(23).Shard);

                // Delete the mapping
                newMappingToDelete = newMultiTenantShardMap.UpdateMapping(
                    newMappingToDelete,
                    new RangeMappingUpdate
                {
                    Status = MappingStatus.Offline,
                });

                newMultiTenantShardMap.DeleteMapping(newMappingToDelete);

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                validationFailed = false;

                try
                {
                    using (SqlConnection conn = newMultiTenantShardMap.OpenConnection(
                               newMappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate))
                    {
                    }
                }
                catch (ShardManagementException smme)
                {
                    validationFailed = true;
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                }

                Assert.AreEqual(validationFailed, true);

                #endregion

                #region OpenConnectionAsync without Validation

                using (SqlConnection conn = multiTenantShardMap.OpenConnectionForKeyAsync(
                           20,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None).Result)
                {
                }

                #endregion

                #region OpenConnectionAsync with Validation

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                validationFailed = false;
                try
                {
                    using (SqlConnection conn = multiTenantShardMap.OpenConnectionAsync(
                               mappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate).Result)
                    {
                    }
                }
                catch (AggregateException ex)
                {
                    ShardManagementException smme = ex.InnerException as ShardManagementException;
                    if (smme != null)
                    {
                        validationFailed = true;
                        Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                    }
                }

                Assert.AreEqual(validationFailed, true);

                #endregion

                #region OpenConnectionAsync without Validation and Empty Cache

                // Obtain new shard map manager instance
                newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the Range Shard Map
                newMultiTenantShardMap = newShardMapManager.GetRangeShardMap <int>(rangeShardMapName);

                using (SqlConnection conn = newMultiTenantShardMap.OpenConnectionForKeyAsync(
                           20,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None).Result)
                {
                }

                #endregion

                #region OpenConnectionAsync with Validation and Empty Cache

                // Obtain new shard map manager instance
                newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the Range Shard Map
                newMultiTenantShardMap = newShardMapManager.GetRangeShardMap <int>(rangeShardMapName);

                // Create a new mapping
                newMappingToDelete = newMultiTenantShardMap.CreateRangeMapping(
                    new Range <int>(70, 80),
                    newMultiTenantShardMap.GetMappingForKey(23).Shard);

                // Delete the mapping
                newMappingToDelete = newMultiTenantShardMap.UpdateMapping(
                    newMappingToDelete,
                    new RangeMappingUpdate
                {
                    Status = MappingStatus.Offline,
                });

                newMultiTenantShardMap.DeleteMapping(newMappingToDelete);

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                validationFailed = false;
                try
                {
                    using (SqlConnection conn = newMultiTenantShardMap.OpenConnectionAsync(
                               newMappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate).Result)
                    {
                    }
                }
                catch (AggregateException ex)
                {
                    ShardManagementException smme = ex.InnerException as ShardManagementException;
                    if (smme != null)
                    {
                        validationFailed = true;
                        Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                    }
                }

                Assert.AreEqual(validationFailed, true);

                #endregion

                #region GetMapping

                // Perform tenant lookup. This will populate the cache.
                for (int i = 0; i < ScenarioTests.s_multiTenantDBs.Length; i++)
                {
                    RangeMapping <int> result = shardMapManager
                                                .GetRangeShardMap <int>("MultiTenantShardMap")
                                                .GetMappingForKey((i + 1) * 10);

                    Trace.WriteLine(result.Shard.Location);

                    if (i == 0)
                    {
                        // Since we moved [10,20) to database 1 earlier.
                        Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_multiTenantDBs[0]);
                    }
                    else
                    if (i < 4)
                    {
                        Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_multiTenantDBs[i + 1]);
                    }
                    else
                    {
                        Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_multiTenantDBs[2]);
                    }
                }

                // Perform tenant lookup. This will read from the cache.
                for (int i = 0; i < ScenarioTests.s_multiTenantDBs.Length; i++)
                {
                    RangeMapping <int> result = shardMapManager
                                                .GetRangeShardMap <int>("MultiTenantShardMap")
                                                .GetMappingForKey((i + 1) * 10);

                    Trace.WriteLine(result.Shard.Location);

                    if (i == 0)
                    {
                        // Since we moved [10,20) to database 1 earlier.
                        Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_multiTenantDBs[0]);
                    }
                    else
                    if (i < 4)
                    {
                        Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_multiTenantDBs[i + 1]);
                    }
                    else
                    {
                        Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_multiTenantDBs[2]);
                    }
                }

                #endregion GetMapping

                #region Split/Merge

                int splitPoint = 55;

                // Split [50, 60) into [50, 55) and [55, 60)
                RangeMapping <int> mappingToSplit = multiTenantShardMap.GetMappingForKey(splitPoint);

                IReadOnlyList <RangeMapping <int> > rangesAfterSplit = multiTenantShardMap.SplitMapping(mappingToSplit, splitPoint);

                rangesAfterSplit = rangesAfterSplit.OrderBy(nr => nr.Value.Low).ToArray();

                // We should get 2 ranges back.
                Assert.AreEqual(2, rangesAfterSplit.Count);

                Assert.AreEqual(rangesAfterSplit[0].Value.Low, new Range <int>(50, 55).Low);
                Assert.AreEqual(rangesAfterSplit[0].Value.High, new Range <int>(50, 55).High);
                Assert.AreEqual(rangesAfterSplit[1].Value.Low, new Range <int>(55, 60).Low);
                Assert.AreEqual(rangesAfterSplit[1].Value.High, new Range <int>(55, 60).High);

                // Split [50, 55) into [50, 52) and [52, 55)
                IReadOnlyList <RangeMapping <int> > newRangesAfterAdd = multiTenantShardMap.SplitMapping(rangesAfterSplit[0], 52);

                newRangesAfterAdd = newRangesAfterAdd.OrderBy(nr => nr.Value.Low).ToArray();

                // We should get 2 ranges back.
                Assert.AreEqual(2, newRangesAfterAdd.Count);

                Assert.AreEqual(newRangesAfterAdd[0].Value.Low, new Range <int>(50, 52).Low);
                Assert.AreEqual(newRangesAfterAdd[0].Value.High, new Range <int>(50, 52).High);
                Assert.AreEqual(newRangesAfterAdd[1].Value.Low, new Range <int>(52, 55).Low);
                Assert.AreEqual(newRangesAfterAdd[1].Value.High, new Range <int>(52, 55).High);

                // Move [50, 52) to MultiTenantDB1

                Shard targetShard = multiTenantShardMap.GetShard(new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, ScenarioTests.s_multiTenantDBs[0]));

                // Mark mapping offline, update shard location.
                RangeMapping <int> movedMapping1 = MarkMappingOfflineAndUpdateShard <int>(
                    multiTenantShardMap, newRangesAfterAdd[0], targetShard);

                // Bring the mapping back online.
                movedMapping1 = multiTenantShardMap.UpdateMapping(
                    movedMapping1,
                    new RangeMappingUpdate
                {
                    Status = MappingStatus.Online,
                });


                // Mark mapping offline, update shard location.
                RangeMapping <int> movedMapping2 = MarkMappingOfflineAndUpdateShard <int>(
                    multiTenantShardMap, newRangesAfterAdd[1], targetShard);

                // Bring the mapping back online.
                movedMapping2 = multiTenantShardMap.UpdateMapping(
                    movedMapping2,
                    new RangeMappingUpdate
                {
                    Status = MappingStatus.Online,
                });

                // Obtain the final moved mapping.
                RangeMapping <int> finalMovedMapping = multiTenantShardMap.MergeMappings(movedMapping1, movedMapping2);

                Assert.AreEqual(finalMovedMapping.Value.Low, new Range <int>(50, 55).Low);
                Assert.AreEqual(finalMovedMapping.Value.High, new Range <int>(50, 55).High);

                #endregion Split/Merge
            }
            catch (ShardManagementException smme)
            {
                success = false;

                Trace.WriteLine(String.Format("Error Category: {0}", smme.ErrorCategory));
                Trace.WriteLine(String.Format("Error Code    : {0}", smme.ErrorCode));
                Trace.WriteLine(String.Format("Error Message : {0}", smme.Message));

                if (smme.InnerException != null)
                {
                    Trace.WriteLine(String.Format("Storage Error Message : {0}", smme.InnerException.Message));

                    if (smme.InnerException.InnerException != null)
                    {
                        Trace.WriteLine(String.Format("SqlClient Error Message : {0}", smme.InnerException.InnerException.Message));
                    }
                }
            }

            Assert.IsTrue(success);
        }
예제 #6
0
        public void BasicScenarioListShardMaps()
        {
            bool   success      = true;
            string shardMapName = "PerTenantShardMap";

            try
            {
                #region DeployShardMapManager

                // Deploy shard map manager.
                ShardMapManagerFactory.CreateSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerCreateMode.ReplaceExisting);

                #endregion DeployShardMapManager

                #region GetShardMapManager

                // Obtain shard map manager.
                ShardMapManager shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                #endregion GetShardMapManager

                #region CreateListShardMap

                // Create a single user per-tenant shard map.
                ListShardMap <int> perTenantShardMap = shardMapManager.CreateListShardMap <int>(shardMapName);

                #endregion CreateListShardMap

                #region CreateShardAndPointMapping

                for (int i = 0; i < ScenarioTests.s_perTenantDBs.Length; i++)
                {
                    // Create the shard.
                    Shard s = perTenantShardMap.CreateShard(
                        new ShardLocation(
                            Globals.ShardMapManagerTestsDatasourceName,
                            ScenarioTests.s_perTenantDBs[i]));

                    // Create the mapping.
                    PointMapping <int> p = perTenantShardMap.CreatePointMapping(
                        i + 1,
                        s);
                }

                #endregion CreateShardAndPointMapping

                #region UpdatePointMapping

                // Let's add another point 5 and map it to same shard as 1.

                PointMapping <int> mappingForOne = perTenantShardMap.GetMappingForKey(1);

                PointMapping <int> mappingForFive = perTenantShardMap.CreatePointMapping(5, mappingForOne.Shard);

                Assert.IsTrue(mappingForOne.Shard.Location.Equals(mappingForFive.Shard.Location));

                // Move 3 from PerTenantDB3 to PerTenantDB for 5.
                PointMapping <int> mappingToUpdate = perTenantShardMap.GetMappingForKey(3);
                bool updateFailed = false;

                // Try updating that shard in the mapping without taking it offline first.
                try
                {
                    perTenantShardMap.UpdateMapping(
                        mappingToUpdate,
                        new PointMappingUpdate
                    {
                        Shard = mappingForFive.Shard
                    });
                }
                catch (ShardManagementException smme)
                {
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingIsNotOffline);
                    updateFailed = true;
                }

                Assert.IsTrue(updateFailed);

                // Perform the actual update.
                PointMapping <int> newMappingFor3 = MarkMappingOfflineAndUpdateShard <int>(
                    perTenantShardMap, mappingToUpdate, mappingForFive.Shard);

                // Verify that update succeeded.
                Assert.IsTrue(newMappingFor3.Shard.Location.Equals(mappingForFive.Shard.Location));
                Assert.IsTrue(newMappingFor3.Status == MappingStatus.Offline);

                // Update custom field for the updated mapping.
                //PointMapping<int> veryNewMappingFor3 = perTenantShardMap.UpdatePointMapping(
                //    newMappingFor3,
                //    new PointMappingUpdate
                //    {
                //        Custom = new byte[] { 0x12, 0x34 }
                //    });

                #endregion UpdatePointMapping

                #region DeleteMapping

                // Find the shard by location.
                PointMapping <int> mappingToDelete = perTenantShardMap.GetMappingForKey(5);
                bool operationFailed = false;

                // Try to delete mapping while it is online, the delete should fail.
                try
                {
                    perTenantShardMap.DeleteMapping(mappingToDelete);
                }
                catch (ShardManagementException smme)
                {
                    operationFailed = true;
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingIsNotOffline);
                }

                Trace.Assert(operationFailed);

                // The mapping must be taken offline first before it can be deleted.
                mappingToDelete = perTenantShardMap.UpdateMapping(
                    mappingToDelete,
                    new PointMappingUpdate
                {
                    Status = MappingStatus.Offline,
                });

                perTenantShardMap.DeleteMapping(mappingToDelete);

                // Verify that delete succeeded.
                try
                {
                    PointMapping <int> deletedMapping = perTenantShardMap.GetMappingForKey(5);
                }
                catch (ShardManagementException smme)
                {
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingNotFoundForKey);
                }

                #endregion DeleteMapping

                #region OpenConnection without Validation

                using (SqlConnection conn = perTenantShardMap.OpenConnectionForKey(
                           2,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None))
                {
                }

                #endregion OpenConnection without Validation

                #region OpenConnection with Validation

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                bool validationFailed = false;
                try
                {
                    using (SqlConnection conn = perTenantShardMap.OpenConnection(
                               mappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate))
                    {
                    }
                }
                catch (ShardManagementException smme)
                {
                    validationFailed = true;
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                }

                Assert.AreEqual(validationFailed, true);

                #endregion OpenConnection with Validation

                #region OpenConnection without Validation and Empty Cache

                // Obtain a new ShardMapManager instance
                ShardMapManager newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the ShardMap
                ListShardMap <int> newPerTenantShardMap = newShardMapManager.GetListShardMap <int>(shardMapName);

                using (SqlConnection conn = newPerTenantShardMap.OpenConnectionForKey(
                           2,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None))
                {
                }

                #endregion

                #region OpenConnection with Validation and Empty Cache

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                validationFailed = false;

                // Obtain a new ShardMapManager instance
                newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the ShardMap
                newPerTenantShardMap = newShardMapManager.GetListShardMap <int>(shardMapName);

                // Create a new mapping
                PointMapping <int> newMappingToDelete = newPerTenantShardMap.CreatePointMapping(6,
                                                                                                newPerTenantShardMap.GetMappingForKey(1).Shard);

                // Delete the mapping
                newMappingToDelete = newPerTenantShardMap.UpdateMapping(
                    newMappingToDelete,
                    new PointMappingUpdate
                {
                    Status = MappingStatus.Offline,
                });

                newPerTenantShardMap.DeleteMapping(newMappingToDelete);

                try
                {
                    using (SqlConnection conn = newPerTenantShardMap.OpenConnection(
                               newMappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate))
                    {
                    }
                }
                catch (ShardManagementException smme)
                {
                    validationFailed = true;
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                }

                Assert.AreEqual(validationFailed, true);

                #endregion

                #region OpenConnectionAsync without Validation

                using (SqlConnection conn = perTenantShardMap.OpenConnectionForKeyAsync(
                           2,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None).Result)
                {
                }

                #endregion

                #region OpenConnectionAsync with Validation

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                validationFailed = false;
                try
                {
                    using (SqlConnection conn = perTenantShardMap.OpenConnectionAsync(
                               mappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate).Result)
                    {
                    }
                }
                catch (AggregateException ex)
                {
                    ShardManagementException smme = ex.InnerException as ShardManagementException;
                    if (smme != null)
                    {
                        validationFailed = true;
                        Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                    }
                }

                Assert.AreEqual(validationFailed, true);

                #endregion

                #region OpenConnectionAsync without Validation and Empty Cache

                // Obtain a new ShardMapManager instance
                newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the ShardMap
                newPerTenantShardMap = newShardMapManager.GetListShardMap <int>(shardMapName);
                using (SqlConnection conn = newPerTenantShardMap.OpenConnectionForKeyAsync(
                           2,
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None).Result)
                {
                }

                #endregion

                #region OpenConnectionAsync with Validation and Empty Cache

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                validationFailed = false;

                // Obtain a new ShardMapManager instance
                newShardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                // Get the ShardMap
                newPerTenantShardMap = newShardMapManager.GetListShardMap <int>(shardMapName);

                // Create a new mapping
                newMappingToDelete = newPerTenantShardMap.CreatePointMapping(6,
                                                                             newPerTenantShardMap.GetMappingForKey(1).Shard);

                // Delete the mapping
                newMappingToDelete = newPerTenantShardMap.UpdateMapping(
                    newMappingToDelete,
                    new PointMappingUpdate
                {
                    Status = MappingStatus.Offline,
                });

                newPerTenantShardMap.DeleteMapping(newMappingToDelete);

                try
                {
                    using (SqlConnection conn = newPerTenantShardMap.OpenConnectionAsync(
                               newMappingToDelete,
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate).Result)
                    {
                    }
                }
                catch (AggregateException ex)
                {
                    ShardManagementException smme = ex.InnerException as ShardManagementException;
                    if (smme != null)
                    {
                        validationFailed = true;
                        Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.MappingDoesNotExist);
                    }
                }

                Assert.AreEqual(validationFailed, true);

                #endregion

                #region LookupPointMapping

                // Perform tenant lookup. This will populate the cache.
                for (int i = 0; i < ScenarioTests.s_perTenantDBs.Length; i++)
                {
                    PointMapping <int> result = shardMapManager
                                                .GetListShardMap <int>("PerTenantShardMap")
                                                .GetMappingForKey(i + 1);

                    Trace.WriteLine(result.Shard.Location);

                    // Since we moved 3 to database 1 earlier.
                    Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_perTenantDBs[i != 2 ? i : 0]);
                }

                // Perform tenant lookup. This will read from the cache.
                for (int i = 0; i < ScenarioTests.s_perTenantDBs.Length; i++)
                {
                    PointMapping <int> result = shardMapManager
                                                .GetListShardMap <int>("PerTenantShardMap")
                                                .GetMappingForKey(i + 1);

                    Trace.WriteLine(result.Shard.Location);

                    // Since we moved 3 to database 1 earlier.
                    Assert.IsTrue(result.Shard.Location.Database == ScenarioTests.s_perTenantDBs[i != 2 ? i : 0]);
                }

                #endregion LookupPointMapping
            }
            catch (ShardManagementException smme)
            {
                success = false;

                Trace.WriteLine(String.Format("Error Category: {0}", smme.ErrorCategory));
                Trace.WriteLine(String.Format("Error Code    : {0}", smme.ErrorCode));
                Trace.WriteLine(String.Format("Error Message : {0}", smme.Message));

                if (smme.InnerException != null)
                {
                    Trace.WriteLine(String.Format("Storage Error Message : {0}", smme.InnerException.Message));

                    if (smme.InnerException.InnerException != null)
                    {
                        Trace.WriteLine(String.Format("SqlClient Error Message : {0}", smme.InnerException.InnerException.Message));
                    }
                }
            }

            Assert.IsTrue(success);
        }
예제 #7
0
        public void BasicScenarioDefaultShardMaps()
        {
            bool success = true;

            try
            {
                #region DeployShardMapManager

                // Deploy shard map manager.
                ShardMapManagerFactory.CreateSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerCreateMode.ReplaceExisting);

                #endregion DeployShardMapManager

                #region GetShardMapManager

                // Obtain shard map manager.
                ShardMapManager shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                #endregion GetShardMapManager

                #region CreateDefaultShardMap

                // Create a single user per-tenant shard map.
                ShardMap defaultShardMap = shardMapManager.CreateListShardMap <int>("DefaultShardMap");

                #endregion CreateDefaultShardMap

                #region CreateShard

                for (int i = 0; i < ScenarioTests.s_perTenantDBs.Length; i++)
                {
                    // Create the shard.
                    defaultShardMap.CreateShard(
                        new ShardLocation(
                            Globals.ShardMapManagerTestsDatasourceName,
                            ScenarioTests.s_perTenantDBs[i]));
                }

                #endregion CreateShard

                #region UpdateShard

                // Find the shard by location.
                Shard shardToUpdate = defaultShardMap.GetShard(new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, "PerTenantDB1"));

                // Perform the actual update. Mark offline.
                Shard updatedShard = defaultShardMap.UpdateShard(
                    shardToUpdate,
                    new ShardUpdate
                {
                    Status = ShardStatus.Offline
                });

                // Verify that update succeeded.
                Assert.AreEqual(ShardStatus.Offline, updatedShard.Status);

                #endregion UpdateShard

                #region DeleteShard

                // Find the shard by location.
                Shard shardToDelete = defaultShardMap.GetShard(new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, "PerTenantDB4"));

                defaultShardMap.DeleteShard(shardToDelete);

                // Verify that delete succeeded.
                Shard deletedShard;

                defaultShardMap.TryGetShard(shardToDelete.Location, out deletedShard);

                Assert.IsNull(deletedShard);

                // Now add the shard back for further tests.
                // Create the shard.
                defaultShardMap.CreateShard(shardToDelete.Location);

                #endregion DeleteShard

                #region OpenConnection without Validation

                // Find the shard by location.
                Shard shardForConnection = defaultShardMap.GetShard(new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, "PerTenantDB1"));

                using (SqlConnection conn = shardForConnection.OpenConnection(
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None)) // validate = false
                {
                }

                #endregion OpenConnection without Validation

                #region OpenConnection with Validation

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                bool validationFailed = false;
                try
                {
                    using (SqlConnection conn = shardToDelete.OpenConnection(
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate)) // validate = true
                    {
                    }
                }
                catch (ShardManagementException smme)
                {
                    validationFailed = true;
                    Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.ShardDoesNotExist);
                }

                Assert.AreEqual(validationFailed, true);

                #endregion OpenConnection with Validation

                #region OpenConnectionAsync without Validation

                // Find the shard by location.
                shardForConnection = defaultShardMap.GetShard(new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, "PerTenantDB1"));

                using (SqlConnection conn = shardForConnection.OpenConnectionAsync(
                           Globals.ShardUserConnectionString,
                           ConnectionOptions.None).Result) // validate = false
                {
                }

                #endregion OpenConnectionAsync without Validation

                #region OpenConnectionAsync with Validation

                // Use the stale state of "shardToUpdate" shard & see if validation works.
                validationFailed = false;
                try
                {
                    using (SqlConnection conn = shardToDelete.OpenConnectionAsync(
                               Globals.ShardUserConnectionString,
                               ConnectionOptions.Validate).Result) // validate = true
                    {
                    }
                }
                catch (AggregateException ex)
                {
                    ShardManagementException smme = ex.InnerException as ShardManagementException;
                    if (smme != null)
                    {
                        validationFailed = true;
                        Assert.AreEqual(smme.ErrorCode, ShardManagementErrorCode.ShardDoesNotExist);
                    }
                }

                Assert.AreEqual(validationFailed, true);

                #endregion OpenConnectionAsync with Validation

#if FUTUREWORK
                #region GetAllOnlineShards

                // Get all online shards.
                foreach (Shard s in defaultShardMap.GetShards(Int32.MaxValue, 1))
                {
                    Trace.WriteLine(s.Location);
                }

                #endregion GetAllOnlineShards
#endif
            }
            catch (ShardManagementException smme)
            {
                success = false;

                Trace.WriteLine(String.Format("Error Category: {0}", smme.ErrorCategory));
                Trace.WriteLine(String.Format("Error Code    : {0}", smme.ErrorCode));
                Trace.WriteLine(String.Format("Error Message : {0}", smme.Message));

                if (smme.InnerException != null)
                {
                    Trace.WriteLine(String.Format("Storage Error Message : {0}", smme.InnerException.Message));

                    if (smme.InnerException.InnerException != null)
                    {
                        Trace.WriteLine(String.Format("SqlClient Error Message : {0}", smme.InnerException.InnerException.Message));
                    }
                }
            }

            Assert.IsTrue(success);
        }
        public void TestShardMapManagerExceptionSerializability()
        {
            var errorCategory = ShardManagementErrorCategory.RangeShardMap;
            var errorCode = ShardManagementErrorCode.ShardMapDoesNotExist;

            ShardManagementException ex = new ShardManagementException(errorCategory, errorCode, "Testing");
            string exceptionToString = ex.ToString();

            // Serialize and de-serialize with a BinaryFormatter
            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                // Serialize
                bf.Serialize(ms, ex);

                // Deserialize
                ms.Seek(0, 0);
                ex = (ShardManagementException)bf.Deserialize(ms);
            }

            // Validate
            Assert.AreEqual(ex.ErrorCode, errorCode, "ErrorCode");
            Assert.AreEqual(ex.ErrorCategory, errorCategory, "ErrorCategory");
            Assert.AreEqual(exceptionToString, ex.ToString(), "ToString()");
        }
예제 #9
0
        protected void AssertThrowsShardManagementException(Action a, ShardManagementErrorCode expectedCode)
        {
            ShardManagementException smme = Assert.ThrowsException <ShardManagementException>(a);

            Assert.AreEqual(ShardManagementErrorCode.MappingNotFoundForKey, smme.ErrorCode);
        }