public void LoadTestMarkAllShardsAsOnlineInListShardMap()
        {
            try
            {
                ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                ListShardMap <int> lsm = smm.GetListShardMap <int>(ShardMapManagerLoadTests.s_listShardMapName);
                Assert.IsNotNull(lsm);

                foreach (Shard s in lsm.GetShards())
                {
                    if (s.Status == ShardStatus.Offline)
                    {
                        lsm.UpdateShard(s,
                                        new ShardUpdate
                        {
                            Status = ShardStatus.Online
                        });
                    }
                }
            }
            catch (ShardManagementException sme)
            {
                Debug.WriteLine("Exception caught: {0}", sme.Message);
            }
        }
Beispiel #2
0
        private static Shard CreateOrGetEmptyShard(ListShardMap <int> shardMap)
        {
            // Get an empty shard if one already exists, otherwise create a new one
            Shard shard = FindEmptyShard(shardMap);

            if (shard == null)
            {
                // No empty shard exists, so create one

                // Choose the shard name
                string databaseName = string.Format(ShardNameFormat, shardMap.GetShards().Count());

                // Only create the database if it doesn't already exist. It might already exist if
                // we tried to create it previously but hit a transient fault.
                if (!SqlDatabaseUtils.DatabaseExists(Configuration.ShardMapManagerServerName, databaseName))
                {
                    SqlDatabaseUtils.CreateDatabase(Configuration.ShardMapManagerServerName, databaseName);
                }

                // Create schema and populate reference data on that database
                // The initialize script must be idempotent, in case it was already run on this database
                // and we failed to add it to the shard map previously
                SqlDatabaseUtils.ExecuteSqlScript(
                    Configuration.ShardMapManagerServerName, databaseName, InitializeShardScriptFile);

                // Add it to the shard map
                ShardLocation shardLocation = new ShardLocation(Configuration.ShardMapManagerServerName, databaseName);
                shard = ShardManagementUtils.CreateOrGetShard(shardMap, shardLocation);
            }

            return(shard);
        }
        public void LoadTestRemoveShardFromListShardMap()
        {
            try
            {
                ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                    Globals.ShardMapManagerConnectionString,
                    ShardMapManagerLoadPolicy.Lazy);

                ListShardMap <int> lsm = smm.GetListShardMap <int>(ShardMapManagerLoadTests.s_listShardMapName);
                Assert.IsNotNull(lsm);

                List <Shard> existingShards = lsm.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 = lsm.UpdateShard(offlineShard,
                                                   new ShardUpdate
                    {
                        Status = ShardStatus.Offline
                    });
                }

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

                PointMappingUpdate pu = new PointMappingUpdate();
                pu.Status = MappingStatus.Offline;

                // Remove all mappings from this shard for given shard map.
                foreach (PointMapping <int> p in lsm.GetMappings(offlineShard))
                {
                    PointMapping <int> mappingToDelete = lsm.UpdateMapping(p, pu);
                    lsm.DeleteMapping(mappingToDelete);
                }

                // Shard object is changed as mappings are removed, get it again.
                Shard deleteShard = lsm.GetShard(offlineShard.Location);

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

                Debug.WriteLine("Removed shard at location {0} from shard map {1}", deleteShard.Location, lsm);
            }
            catch (ShardManagementException sme)
            {
                Debug.WriteLine("Exception caught: {0}", sme.Message);
            }
        }
Beispiel #4
0
        public IEnumerable <string> GetAllShards()
        {
            string prefix = $"{_shardingConfig.ShardPrefix}.";

            return(_shardMap.GetShards().Select(s =>
                                                s.Location.Database.Split(new string[] { prefix },
                                                                          StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()));
        }
        public bool DeleteShardListMap()
        {
            try
            {
                if (ShardMapManager == null)
                {
                    return(false);
                }
                Shard tempShard = null;
                PointMapping <long> tempMapping = null;

                if (ShardMapManager.TryGetListShardMap(mapManagerName, out lsm))
                {
                    foreach (Shard shard in lsm.GetShards())
                    {
                        // delete all mappings
                        var allMappings = lsm.GetMappings(shard);
                        for (int i = 0; i < allMappings.Count; i++)
                        {
                            lsm.MarkMappingOffline(allMappings[i]);
                            if (lsm.TryGetMappingForKey(allMappings[i].Value, out tempMapping))
                            {
                                lsm.DeleteMapping(tempMapping);
                            }
                        }
                        // delete shard
                        if (lsm.TryGetShard(shard.Location, out tempShard))
                        {
                            lsm.DeleteShard(tempShard);
                        }
                    }
                }
                // clear shard map manager
                if (ShardMapManager.TryGetListShardMap(mapManagerName, out lsm))
                {
                    ShardMapManager.DeleteShardMap(lsm);
                }

                return(true);
            }
            catch { return(false); }
        }
        /// <summary>
        /// Writes the shard map's state to the console.
        /// </summary>
        private static void PrintShardMapState()
        {
            Console.WriteLine("Current Shard Map state:");
            ListShardMap <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);
            var 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))
                {
                    var 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");
            }
        }
        private Shard FindEmptyShard(ListShardMap <int> shardMap)
        {
            // Get all shards in the shard map
            IEnumerable <Shard> allShards = shardMap.GetShards();

            // Get all mappings in the shard map
            IEnumerable <PointMapping <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>
        /// Drops all shards and the shard map manager database (if it exists).
        /// </summary>
        private static void DropAll()
        {
            ListShardMap <int> shardMap = TryGetShardMap();

            if (shardMap != null)
            {
                // Drop shards
                foreach (Shard shard in shardMap.GetShards())
                {
                    SqlDatabaseUtils.DropDatabase(shard.Location.DataSource, shard.Location.Database);
                }
            }

            if (SqlDatabaseUtils.DatabaseExists(Configuration.ShardMapManagerServerName, Configuration.ShardMapManagerDatabaseName))
            {
                // Drop shard map manager database
                SqlDatabaseUtils.DropDatabase(Configuration.ShardMapManagerServerName, Configuration.ShardMapManagerDatabaseName);
            }

            // Since we just dropped the shard map manager database, this shardMapManager reference is now non-functional.
            // So set it to null so that the program knows that the shard map manager is gone.
            s_shardMapManager = null;
        }
        /// <summary>
        /// Creates a shard map manager, creates a shard map, and creates a shard
        /// with a mapping for the full range of 32-bit integers.
        /// </summary>
        private static void CreateShardMapManagerAndShard()
        {
            if (s_shardMapManager != null)
            {
                ConsoleUtils.WriteWarning("Shard Map Manager already exists");
                return;
            }

            // Create shard map manager database
            if (!SqlDatabaseUtils.DatabaseExists(Configuration.ShardMapManagerServerName, Configuration.ShardMapManagerDatabaseName))
            {
                SqlDatabaseUtils.CreateDatabase(Configuration.ShardMapManagerServerName, Configuration.ShardMapManagerDatabaseName);
            }

            // Create shard map manager
            string shardMapManagerConnectionString =
                Configuration.GetConnectionString(
                    Configuration.ShardMapManagerServerName,
                    Configuration.ShardMapManagerDatabaseName);

            s_shardMapManager = ShardManagementUtils.CreateOrGetShardMapManager(shardMapManagerConnectionString);

            // Create shard map
            ListShardMap <int> shardMap = ShardManagementUtils.CreateOrGetRangeShardMap <int>(
                s_shardMapManager, Configuration.ShardMapName);

            // Create schema info so that the split-merge service can be used to move data in sharded tables
            // and reference tables.
            CreateSchemaInfo(shardMap.Name);

            // If there are no shards, add two shards: one for [0,100) and one for [100,+inf)
            if (!shardMap.GetShards().Any())
            {
                CreateShardSample.CreateShard(shardMap, 1);
                CreateShardSample.CreateShard(shardMap, 2);
            }
        }
Beispiel #10
0
        public List <string[]> ExecuteMultiShardQuery(ListShardMap <int> shardMap, string credentialsConnectionString)
        {
            // Get the shards to connect to
            IEnumerable <Shard> shards = shardMap.GetShards();

            // Create the multi-shard connection
            using (MultiShardConnection conn = new MultiShardConnection(shards, credentialsConnectionString))
            {
                // Create a simple command
                using (MultiShardCommand cmd = conn.CreateCommand())
                {
                    // Because this query is grouped by CustomerID, which is sharded,
                    // we will not get duplicate rows.
                    cmd.CommandText = @"
                        SELECT 
                            c.CustomerId, 
                            c.Name AS CustomerName, 
                            o.OrderID AS OrderCount
                        FROM 
                            dbo.Customers AS c INNER JOIN 
                            dbo.Orders AS o
                            ON c.CustomerID = o.CustomerID
                        
                        ORDER BY 
                            1";

                    // Append a column with the shard name where the row came from
                    cmd.ExecutionOptions = MultiShardExecutionOptions.IncludeShardNameColumn;

                    // Allow for partial results in case some shards do not respond in time
                    cmd.ExecutionPolicy = MultiShardExecutionPolicy.PartialResults;

                    // Allow the entire command to take up to 30 seconds
                    cmd.CommandTimeout = 30;

                    // Execute the command.
                    // We do not need to specify retry logic because MultiShardDataReader will internally retry until the CommandTimeout expires.
                    using (MultiShardDataReader reader = cmd.ExecuteReader())
                    {
                        // Get the column names
                        TableFormatter formatter = new TableFormatter(GetColumnNames(reader).ToArray());

                        int rows = 0;
                        while (reader.Read())
                        {
                            // Read the values using standard DbDataReader methods
                            object[] values = new object[reader.FieldCount];
                            reader.GetValues(values);

                            // Extract just database name from the $ShardLocation pseudocolumn to make the output formater cleaner.
                            // Note that the $ShardLocation pseudocolumn is always the last column
                            int shardLocationOrdinal = values.Length - 1;
                            values[shardLocationOrdinal] = ExtractDatabaseName(values[shardLocationOrdinal].ToString());

                            // Add values to output formatter
                            formatter.AddRow(values);

                            rows++;
                        }

                        Console.WriteLine(formatter.ToString());
                        Console.WriteLine("({0} rows returned)", rows);

                        return(formatter._rows);
                    }
                }
            }
        }
        public void ConcurrencyScenarioListShardMap()
        {
            bool operationFailed; // variable to track status of negative test scenarios

            // Create 2 SMM objects representing management and client

            ShardMapManager smmMgmt = ShardMapManagerFactory.GetSqlShardMapManager(
                Globals.ShardMapManagerConnectionString,
                ShardMapManagerLoadPolicy.Lazy);

            ShardMapManager smmClient = ShardMapManagerFactory.GetSqlShardMapManager(
                Globals.ShardMapManagerConnectionString,
                ShardMapManagerLoadPolicy.Lazy);

            #region CreateShardMap
            // Add a shard map from management SMM.
            ShardMap smMgmt = smmMgmt.CreateListShardMap <int>(ShardMapManagerConcurrencyTests.s_shardMapName);

            Assert.AreEqual(ShardMapManagerConcurrencyTests.s_shardMapName, smMgmt.Name);

            // Lookup shard map from client SMM.
            ShardMap smClient = smmClient.GetShardMap(ShardMapManagerConcurrencyTests.s_shardMapName);

            Assert.IsNotNull(smClient);

            #endregion CreateShardMap

            #region ConvertToListShardMap

            ListShardMap <int> lsmMgmt = smmMgmt.GetListShardMap <int>(ShardMapManagerConcurrencyTests.s_shardMapName);
            Assert.IsNotNull(lsmMgmt);

            // look up shard map again, it will
            ListShardMap <int> lsmClient = smmClient.GetListShardMap <int>(ShardMapManagerConcurrencyTests.s_shardMapName);
            Assert.IsNotNull(lsmClient);

            #endregion ConvertToListShardMap

            #region DeleteShardMap

            // verify that smClient is accessible

            IEnumerable <Shard> shardClient = lsmClient.GetShards();

            smmMgmt.DeleteShardMap(lsmMgmt);

            operationFailed = false;

            try
            {
                // smClient does not exist, below call will fail.
                IEnumerable <Shard> sCNew = lsmClient.GetShards();
            }
            catch (ShardManagementException sme)
            {
                Assert.AreEqual(ShardManagementErrorCategory.ShardMap, sme.ErrorCategory);
                Assert.AreEqual(ShardManagementErrorCode.ShardMapDoesNotExist, sme.ErrorCode);
                operationFailed = true;
            }

            Assert.IsTrue(operationFailed);

            #endregion DeleteShardMap
        }