public static void ExecuteDataDependentRoutingQuery(RangeShardMap<int> shardMap, string credentialsConnectionString)
        {
            // 亂數產生一筆 Key
            //亂數最高範圍
            int currentMaxHighKey = shardMap.GetMappings().Max(m => m.Value.High);
            //亂數取得 CustomerID
            int customerId = GetCustomerId(currentMaxHighKey);
            //亂數產生 Customer Name
            string customerName = s_customerNames[s_r.Next(s_customerNames.Length)];
            int regionId = 0;
            int productId = 0;

            AddCustomer(
                shardMap,
                credentialsConnectionString,
                customerId,
                customerName,
                regionId);

            AddOrder(
                shardMap,
                credentialsConnectionString,
                customerId,
                productId);
        }
        public void LoadTestRemoveShardFromRangeShardMap()
        {
            try
            {
                ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                RangeShardMap <int> rsm = smm.GetRangeShardMap <int>(ShardMapManagerLoadTests.s_rangeShardMapName);
                Assert.IsNotNull(rsm);

                List <Shard> existingShards = rsm.GetShards().ToList();

                if (existingShards.Count == 0)
                {
                    return;
                }

                // If there is already a shard marked as offline, chose that one to delete.
                // This can happend if earlier remove operation was terminated for some reason - ex. killing connections.
                Shard offlineShard = existingShards.Find(e => e.Status == ShardStatus.Offline);

                if (offlineShard == null)
                {
                    offlineShard = existingShards[_r.Next(existingShards.Count)];

                    // First mark shard as offline so that other test threads will not add new mappings to it.
                    offlineShard = rsm.UpdateShard(offlineShard,
                                                   new ShardUpdate
                    {
                        Status = ShardStatus.Offline
                    });
                }

                Debug.WriteLine("Trying to remove shard at location {0}", offlineShard.Location);

                RangeMappingUpdate ru = new RangeMappingUpdate();
                ru.Status = MappingStatus.Offline;

                // Remove all mappings from this shard for given shard map.
                foreach (RangeMapping <int> rm in rsm.GetMappings(offlineShard))
                {
                    RangeMapping <int> mappingToDelete = rsm.UpdateMapping(rm, ru);
                    rsm.DeleteMapping(mappingToDelete);
                }

                // get shard object again.
                Shard deleteShard = rsm.GetShard(offlineShard.Location);

                // now remove shard.
                rsm.DeleteShard(deleteShard);

                Debug.WriteLine("Removed shard at location {0} from shard map {1}", deleteShard.Location, rsm);
            }
            catch (ShardManagementException sme)
            {
                Debug.WriteLine("Exception caught: {0}", sme.Message);
            }
        }
Example #3
0
        /// <summary>
        /// To create database records
        /// </summary>
        /// <param name="shardMap"></param>
        /// <param name="credentialsConnectionString"></param>
        public static void ExecuteDataDependentRoutingQuery(RangeShardMap <int> shardMap)
        {
            // we just choose a random key out of the range that is mapped. Here we assume that the ranges
            // start at 0, are contiguous, and are bounded (i.e. there is no range where HighIsMax == true)
            int currentMaxHighKey = shardMap.GetMappings().Max(m => m.Value.High);

            MultiShardConfiguration.customerId = GetCustomerId(currentMaxHighKey);
            string customerName = shardCustomerNames[randCustomer.Next(shardCustomerNames.Length)];
            int    regionId     = 0;
            int    productId    = 0;

            TestParameterValue testParameterValue
                = new TestParameterValue(
                      "DataDependentRouting", "ExecuteDataDependentRouting", "Insert",
                      "SqlDbWithDataDependent" + "%"
                      + "individual" + "%"
                      + "-",
                      new MyUserInfo("DataDependentRouting", "DataDependentRouting"));

            // 情報の設定
            testParameterValue.CustomerId = MultiShardConfiguration.customerId;
            testParameterValue.Name       = customerName;
            testParameterValue.RegionId   = regionId;
            testParameterValue.ProductId  = productId;

            // 分離レベルの設定
            DbEnum.IsolationLevelEnum iso = DbEnum.IsolationLevelEnum.DefaultTransaction;

            // B層を生成
            LayerB myBusiness = new LayerB();

            // 業務処理を実行
            TestReturnValue testReturnValue =
                (TestReturnValue)myBusiness.DoBusinessLogic(
                    (BaseParameterValue)testParameterValue, iso);

            string strErrorMsg = "";

            if (testReturnValue.ErrorFlag == true)
            {
                // 結果(業務続行可能なエラー)
                strErrorMsg  = "ErrorMessageID:" + testReturnValue.ErrorMessageID + "\r\n";
                strErrorMsg += "ErrorMessage:" + testReturnValue.ErrorMessage + "\r\n";
                strErrorMsg += "ErrorInfo:" + testReturnValue.ErrorInfo + "\r\n";

                Console.WriteLine("Inserted failed for customer ID: {0},{1}", testParameterValue.CustomerId, strErrorMsg);
            }
            else
            {
                // 結果(正常系)
                Console.WriteLine("Inserted order for customer ID: {0}", testParameterValue.CustomerId);
            }
        }
        public void LoadTestMergeRangesWithLock()
        {
            try
            {
                ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                RangeShardMap <int> rsm = smm.GetRangeShardMap <int>(ShardMapManagerLoadTests.s_rangeShardMapName);
                Assert.IsNotNull(rsm);

                IEnumerable <RangeMapping <int> > existingMappings = rsm.GetMappings(new Range <int>(MinMappingPoint, MaxMappingPoint));

                IQueryable <RangeMapping <int> > qr = Queryable.AsQueryable(existingMappings);

                // Find pair of adjacent mappings.
                var test = from a in qr
                           join b in qr on
                           new { a.Range.High.Value, a.StoreMapping.StoreShard.Id, a.StoreMapping.Status } equals
                new { b.Range.Low.Value, b.StoreMapping.StoreShard.Id, b.StoreMapping.Status }
                select new { a, b };

                if (test.Count() > 0)
                {
                    var t = test.First();

                    Debug.WriteLine("Trying to merge range mapping for key range ({0} - {1}) and ({2} - {3})", t.a.Range.Low.Value, t.a.Range.High.Value, t.b.Range.Low.Value, t.b.Range.High.Value);


                    MappingLockToken mappingLockTokenLeft = MappingLockToken.Create();
                    rsm.LockMapping(t.a, mappingLockTokenLeft);

                    MappingLockToken mappingLockTokenRight = MappingLockToken.Create();
                    rsm.LockMapping(t.b, mappingLockTokenLeft);

                    RangeMapping <int> rMerged = rsm.MergeMappings(t.a, t.b, mappingLockTokenLeft, mappingLockTokenRight);

                    Assert.IsNotNull(rMerged);

                    MappingLockToken storeMappingLockToken = rsm.GetMappingLockOwner(rMerged);
                    Assert.AreEqual(storeMappingLockToken, mappingLockTokenLeft, "Expected merged mapping lock id to equal left mapping id!");
                    rsm.UnlockMapping(rMerged, storeMappingLockToken);

                    storeMappingLockToken = rsm.GetMappingLockOwner(rMerged);
                    Assert.AreEqual(storeMappingLockToken, MappingLockToken.NoLock, "Expected merged mapping lock id to equal default mapping id after unlock!");
                }
            }
            catch (ShardManagementException sme)
            {
                Debug.WriteLine("Exception caught: {0}", sme.Message);
            }
        }
        private static Shard FindEmptyShard(RangeShardMap <int> shardMap)
        {
            // Get all shards in the shard map
            IEnumerable <Shard> allShards = shardMap.GetShards();

            // Get all mappings in the shard map
            IEnumerable <RangeMapping <int> > allMappings = shardMap.GetMappings();

            // Determine which shards have mappings
            HashSet <Shard> shardsWithMappings = new HashSet <Shard>(allMappings.Select(m => m.Shard));

            // Get the first shard (ordered by name) that has no mappings, if it exists
            return(allShards.OrderBy(s => s.Location.Database).FirstOrDefault(s => !shardsWithMappings.Contains(s)));
        }
        /// <summary>
        /// Finds an existing empty shard, or returns null if none exist.
        /// </summary>
        private static Shard FindEmptyShard(RangeShardMap<int> shardMap)
        {
            // Get all shards in the shard map
            IEnumerable<Shard> allShards = shardMap.GetShards();

            // Get all mappings in the shard map
            IEnumerable<RangeMapping<int>> allMappings = shardMap.GetMappings();

            // Determine which shards have mappings
            HashSet<Shard> shardsWithMappings = new HashSet<Shard>(allMappings.Select(m => m.Shard));

            // Get the first shard (ordered by name) that has no mappings, if it exists
            return allShards.OrderBy(s => s.Location.Database).FirstOrDefault(s => !shardsWithMappings.Contains(s));
        }
        public void LoadTestAddRangeMapping()
        {
            try
            {
                ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                RangeShardMap <int> rsm = smm.GetRangeShardMap <int>(ShardMapManagerLoadTests.s_rangeShardMapName);

                Assert.IsNotNull(rsm);
                do
                {
                    // Chose a random shard to add mapping.
                    Shard s = GetRandomOnlineShardFromShardMap((ShardMap)rsm);
                    if (s == null)
                    {
                        continue;
                    }

                    // generate a random range to add a new range mapping and verify that its not already mapped.
                    int minKey = _r.Next(MinMappingPoint, MaxMappingPoint);
                    int maxKey = minKey + _r.Next(1, MaxRangeMappingSize);
                    maxKey = (maxKey <= MaxMappingPoint) ? maxKey : MaxMappingPoint;

                    IReadOnlyList <RangeMapping <int> > existingMapping = rsm.GetMappings(new Range <int>(minKey, maxKey));
                    if (existingMapping.Count > 0)
                    {
                        continue;
                    }

                    Debug.WriteLine("Trying to add range mapping for key range ({0} - {1}) to shard location {2}", minKey, maxKey, s.Location);

                    RangeMapping <int> r1 = rsm.CreateRangeMapping(new Range <int>(minKey, maxKey), s);

                    Assert.IsNotNull(r1);

                    // Validate mapping by trying to connect
                    s_retryPolicy.ExecuteAction(
                        () => ValidateImpl(
                            (ShardMap)rsm,
                            minKey));
                }while (false);
            }
            catch (ShardManagementException sme)
            {
                Debug.WriteLine("Exception caught: {0}", sme.Message);
            }
        }
        /// <summary>
        /// Get existing range mapping from a range shard map
        /// </summary>
        /// <param name="lsm">Range shard map</param>
        /// <param name="minimumRangeSize">Minimum size of range mapping, this can be used for AddRangeWithinRange and RemoveRangeFromRange tests</param>
        /// <returns>Valid existing range mapping, null if no range mappings found in given shard map</returns>
        private RangeMapping <int> GetRandomRangeMapping(RangeShardMap <int> rsm, int minimumRangeSize = 1)
        {
            IReadOnlyList <RangeMapping <int> > allMappings = rsm.GetMappings();

            List <RangeMapping <int> > filteredList = new List <RangeMapping <int> >(
                from m in allMappings
                where ((int)m.Range.High.Value - (int)m.Range.Low.Value) >= minimumRangeSize
                select m);

            if (filteredList.Count == 0)
            {
                return(null);
            }

            return(filteredList[_r.Next(filteredList.Count)]);
        }
Example #9
0
        /// <summary>
        /// Writes the shard map's state to the console.
        /// </summary>
        private static void PrintShardMapState()
        {
            Console.WriteLine("Current Shard Map state:");
            RangeShardMap <int> shardMap = TryGetShardMap();

            if (shardMap == null)
            {
                return;
            }

            // Get all shards
            IEnumerable <Shard> allShards = shardMap.GetShards();

            // Get all mappings, grouped by the shard that they are on. We do this all in one go to minimise round trips.
            ILookup <Shard, RangeMapping <int> > mappingsGroupedByShard = shardMap.GetMappings().ToLookup(m => m.Shard);

            if (allShards.Any())
            {
                // The shard map contains some shards, so for each shard (sorted by database name)
                // write out the mappings for that shard
                foreach (Shard shard in shardMap.GetShards().OrderBy(s => s.Location.Database))
                {
                    IEnumerable <RangeMapping <int> > mappingsOnThisShard = mappingsGroupedByShard[shard];

                    if (mappingsOnThisShard.Any())
                    {
                        string mappingsString = string.Join(", ", mappingsOnThisShard.Select(m => m.Value));
                        Console.WriteLine("\t{0} contains key range {1}", shard.Location.Database, mappingsString);
                    }
                    else
                    {
                        Console.WriteLine("\t{0} contains no key ranges.", shard.Location.Database);
                    }
                }
            }
            else
            {
                Console.WriteLine("\tShard Map contains no shards");
            }
        }
        public void LoadTestMergeRangesNoLock()
        {
            try
            {
                ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                RangeShardMap <int> rsm = smm.GetRangeShardMap <int>(ShardMapManagerLoadTests.s_rangeShardMapName);
                Assert.IsNotNull(rsm);

                IEnumerable <RangeMapping <int> > existingMappings = rsm.GetMappings(new Range <int>(MinMappingPoint, MaxMappingPoint));

                IQueryable <RangeMapping <int> > qr = Queryable.AsQueryable(existingMappings);

                // find pair of adjacent mappings.
                var test = from a in qr
                           join b in qr on
                           new { a.Range.High.Value, a.StoreMapping.StoreShard.Id, a.StoreMapping.Status } equals
                new { b.Range.Low.Value, b.StoreMapping.StoreShard.Id, b.StoreMapping.Status }
                select new { a, b };

                if (test.Count() > 0)
                {
                    var t = test.First();

                    Debug.WriteLine("Trying to merge range mapping for key range ({0} - {1}) and ({2} - {3})", t.a.Range.Low.Value, t.a.Range.High.Value, t.b.Range.Low.Value, t.b.Range.High.Value);

                    RangeMapping <int> rMerged = rsm.MergeMappings(t.a, t.b);
                    Assert.IsNotNull(rMerged);
                }
            }
            catch (ShardManagementException sme)
            {
                Debug.WriteLine("Exception caught: {0}", sme.Message);
            }
        }
Example #11
0
        /// <summary>
        /// Reads the user's choice of a split point, and creates a new shard with a mapping for the resulting range.
        /// </summary>
        private static void AddShard()
        {
            RangeShardMap <int> shardMap = TryGetShardMap();

            if (shardMap != null)
            {
                // Here we assume that the ranges start at 0, are contiguous,
                // and are bounded (i.e. there is no range where HighIsMax == true)
                int currentMaxHighKey = shardMap.GetMappings().Max(m => m.Value.High);
                int defaultNewHighKey = currentMaxHighKey + 100;

                Console.WriteLine("A new range with low key {0} will be mapped to the new shard.", currentMaxHighKey);
                int newHighKey = ConsoleUtils.ReadIntegerInput(
                    string.Format("Enter the high key for the new range [default {0}]: ", defaultNewHighKey),
                    defaultNewHighKey,
                    input => input > currentMaxHighKey);

                Range <int> range = new Range <int>(currentMaxHighKey, newHighKey);

                Console.WriteLine();
                Console.WriteLine("Creating shard for range {0}", range);
                CreateShardSample.CreateShard(shardMap, range);
            }
        }
        public static void ExecuteDataDependentRoutingQuery(RangeShardMap <int> shardMap, string credentialsConnectionString)
        {
            // A real application handling a request would need to determine the request's customer ID before connecting to the database.
            // Since this is a demo app, we just choose a random key out of the range that is mapped. Here we assume that the ranges
            // start at 0, are contiguous, and are bounded (i.e. there is no range where HighIsMax == true)
            int    currentMaxHighKey = shardMap.GetMappings().Max(m => m.Value.High);
            int    customerId        = GetCustomerId(currentMaxHighKey);
            string customerName      = s_customerNames[s_r.Next(s_customerNames.Length)];
            int    regionId          = 0;
            int    productId         = 0;

            AddCustomer(
                shardMap,
                credentialsConnectionString,
                customerId,
                customerName,
                regionId);

            AddOrder(
                shardMap,
                credentialsConnectionString,
                customerId,
                productId);
        }
        public static void ExecuteDataDependentRoutingQuery(RangeShardMap<int> shardMap, string credentialsConnectionString)
        {
            // A real application handling a request would need to determine the request's customer ID before connecting to the database.
            // Since this is a demo app, we just choose a random key out of the range that is mapped. Here we assume that the ranges
            // start at 0, are contiguous, and are bounded (i.e. there is no range where HighIsMax == true)
            int currentMaxHighKey = shardMap.GetMappings().Max(m => m.Value.High);
            int customerId = GetCustomerId(currentMaxHighKey);
            string customerName = s_customerNames[s_r.Next(s_customerNames.Length)];
            int regionId = 0;
            int productId = 0;

            AddCustomer(
                shardMap,
                credentialsConnectionString,
                customerId,
                customerName,
                regionId);

            AddOrder(
                shardMap,
                credentialsConnectionString,
                customerId,
                productId);
        }
        /// <summary>
        /// 尋找現有為空的 Shard ,假如沒有回傳 null
        /// </summary>
        private static Shard FindEmptyShard(RangeShardMap<int> shardMap)
        {
            // 從 shard map 取得所有 Shard
            IEnumerable<Shard> allShards = shardMap.GetShards();

            // 從 shard map 取得所有 mappings
            IEnumerable<RangeMapping<int>> allMappings = shardMap.GetMappings();

            // 確認 shards 是否有 mappings
            HashSet<Shard> shardsWithMappings = new HashSet<Shard>(allMappings.Select(m => m.Shard));

            // 取得第一個 shard ( 依據名稱排序 )
            return allShards.OrderBy(s => s.Location.Database).FirstOrDefault(s => !shardsWithMappings.Contains(s));
        }
Example #15
0
        public void TestLockingFixInVersion1_2()
        {
            // Get shard map manager
            ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                Globals.ShardMapManagerConnectionString,
                ShardMapManagerLoadPolicy.Lazy);

            // Upgrade to version 1.1
            smm.UpgradeGlobalStore(new Version(1, 1));

            // Create a range shard map and add few mappings
            RangeShardMap <int> rsm = smm.CreateRangeShardMap <int>(ShardMapManagerUpgradeTests.s_shardMapNames[1]);

            Assert.IsNotNull(rsm);

            Shard s = rsm.CreateShard(new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, ShardMapManagerUpgradeTests.s_shardedDBs[0]));

            Assert.IsNotNull(s);

            RangeMapping <int> m1 = rsm.CreateRangeMapping(new Range <int>(1, 10), s);
            RangeMapping <int> m2 = rsm.CreateRangeMapping(new Range <int>(10, 20), s);
            RangeMapping <int> m3 = rsm.CreateRangeMapping(new Range <int>(20, 30), s);

            // Lock first 2 mappings with same lockownerid and third with a different lock owner id

            MappingLockToken t1 = MappingLockToken.Create();
            MappingLockToken t2 = MappingLockToken.Create();

            rsm.LockMapping(m1, t1);
            rsm.LockMapping(m2, t1);
            rsm.LockMapping(m3, t2);

            // now try to unlock using token t2. In store version 1.1 it will unlock all mappings
            rsm.UnlockMapping(t2);

            foreach (RangeMapping <int> m in rsm.GetMappings())
            {
                Assert.AreEqual(MappingLockToken.NoLock, rsm.GetMappingLockOwner(m));
            }

            // Now upgrade to version 1.2 and try same scenario above.
            smm.UpgradeGlobalStore(new Version(1, 2));

            rsm.LockMapping(m1, t1);
            rsm.LockMapping(m2, t1);
            rsm.LockMapping(m3, t2);

            // Unlock using token t1. It should just unlock 2 mappings and leave last one locked.
            rsm.UnlockMapping(t1);

            Assert.AreEqual(MappingLockToken.NoLock, rsm.GetMappingLockOwner(rsm.GetMappingForKey(5)));
            Assert.AreEqual(MappingLockToken.NoLock, rsm.GetMappingLockOwner(rsm.GetMappingForKey(15)));
            Assert.AreEqual(t2, rsm.GetMappingLockOwner(rsm.GetMappingForKey(25)));

            // Cleanup - Delete all mappings. shard will be removed in test cleanup.
            rsm.UnlockMapping(t2);
            RangeMappingUpdate ru = new RangeMappingUpdate();

            ru.Status = MappingStatus.Offline;

            foreach (RangeMapping <int> m in rsm.GetMappings())
            {
                rsm.DeleteMapping(rsm.UpdateMapping(m, ru));
            }
        }
        /// <summary>
        /// Get existing range mapping from a range shard map
        /// </summary>
        /// <param name="lsm">Range shard map</param>
        /// <param name="minimumRangeSize">Minimum size of range mapping, this can be used for AddRangeWithinRange and RemoveRangeFromRange tests</param>
        /// <returns>Valid existing range mapping, null if no range mappings found in given shard map</returns>
        private RangeMapping<int> GetRandomRangeMapping(RangeShardMap<int> rsm, int minimumRangeSize = 1)
        {
            IReadOnlyList<RangeMapping<int>> allMappings = rsm.GetMappings();

            List<RangeMapping<int>> filteredList = new List<RangeMapping<int>>(
                from m in allMappings
                where ((int)m.Range.High.Value - (int)m.Range.Low.Value) >= minimumRangeSize
                select m);

            if (filteredList.Count == 0)
                return null;

            return filteredList[_r.Next(filteredList.Count)];
        }