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); } }
/// <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)]); }
/// <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); } }
/// <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)); }
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)]; }