public static void Main(string[] args) { try { // Parse command line arguments s_commandLine = new CommandLine(args); if (!s_commandLine.IsValid) { s_commandLine.WriteUsage(); return; } // Get Shard Map Manager ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager( GetConnectionString(), ShardMapManagerLoadPolicy.Eager); Console.WriteLine("Connected to Shard Map Manager"); // Get Shard Map ShardMap map = smm.GetShardMap(s_commandLine.ShardMap); Console.WriteLine("Found {0} shards", map.GetShards().Count()); // Create connection string for MultiShardConnection string connectionString = GetCredentialsConnectionString(); // REPL Console.WriteLine(); while (true) { // Read command from console string commandText = GetCommand(); if (commandText == null) { // Exit requested break; } // Evaluate command string output; using (MultiShardConnection conn = new MultiShardConnection(map.GetShards(), connectionString)) { output = ExecuteCommand(conn, commandText); } // Print output Console.WriteLine(output); } } catch (Exception e) { // Print exception and exit Console.WriteLine(e); return; } }
public void TestMultiShardConnectionConstructorEvaluatesShards() { MultiShardTestUtils.DropAndCreateDatabases(); ShardMap shardMap = MultiShardTestUtils.CreateAndGetTestShardMap(); List <Shard> shards = shardMap.GetShards().ToList(); MultiShardConnection conn = new MultiShardConnection(shards.ToConsumable(), dummyConnectionString); AssertExtensions.AssertSequenceEqual(shards, conn.Shards); }
/// <summary> /// Helper function to select a random shard for specified shard map. /// </summary> /// <param name="sm">Shard map to get shard.</param> /// <returns>Shard from specified shard map.</returns> private Shard GetRandomOnlineShardFromShardMap(ShardMap sm) { List <Shard> shardList = sm.GetShards().Where(s => s.Status == ShardStatus.Online).ToList(); if (shardList.Count > 0) { return(shardList[_r.Next(shardList.Count)]); } else { return(null); } }
/// <summary> /// Helper function to add a new shard to given shard map. /// </summary> /// <param name="sm"></param> private void AddShardToShardMap(ShardMap sm) { IEnumerable <Shard> existingShards = sm.GetShards(); // get list of shard locations that are not already added to this shard map. List <string> availableLocationList = (from dbName in ShardMapManagerLoadTests.s_shardedDBs where !existingShards.Select(s => s.Location.Database).ToList().Contains(dbName) select dbName).ToList(); if (availableLocationList.Count > 0) { ShardLocation sl = new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, availableLocationList[_r.Next(availableLocationList.Count)]); Debug.WriteLine("Trying to add shard at location {0} to shard map {1}", sl, sm); ShardCreationInfo si = new ShardCreationInfo(sl, ShardStatus.Online); Shard newShard = sm.CreateShard(si); } }
/// <summary> /// Helper function to clean default shard map. /// </summary> private static void CleanShardMapsHelper() { ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager( Globals.ShardMapManagerConnectionString, ShardMapManagerLoadPolicy.Lazy); // Remove all existing mappings from the list shard map. ShardMap sm = smm.GetShardMap(ShardMapTests.s_defaultShardMapName); Assert.IsNotNull(sm); // Remove all shards from list shard map IEnumerable <Shard> s = sm.GetShards(); using (IEnumerator <Shard> sEnum = s.GetEnumerator()) { while (sEnum.MoveNext()) { sm.DeleteShard(sEnum.Current); } } }
public void DeleteShardAbortGSMDoAndLSMUndo() { bool shouldThrow = true; IStoreOperationFactory sof = new StubStoreOperationFactory() { CallBase = true, CreateRemoveShardOperationShardMapManagerIStoreShardMapIStoreShard = (_smm, _sm, _s) => { StubRemoveShardOperation op = new StubRemoveShardOperation(_smm, _sm, _s); op.CallBase = true; op.DoGlobalPostLocalExecuteIStoreTransactionScope = (ts) => { if (shouldThrow) { throw new StoreException("", ShardMapFaultHandlingTests.TransientSqlException); } else { // Call the base function, hack for this behavior is to save current operation, set current to null, restore current operation. var original = op.DoGlobalPostLocalExecuteIStoreTransactionScope; op.DoGlobalPostLocalExecuteIStoreTransactionScope = null; try { return(op.DoGlobalPostLocalExecute(ts)); } finally { op.DoGlobalPostLocalExecuteIStoreTransactionScope = original; } } }; op.UndoLocalSourceExecuteIStoreTransactionScope = (ts) => { if (shouldThrow) { throw new StoreException("", ShardMapFaultHandlingTests.TransientSqlException); } else { // Call the base function, hack for this behavior is to save current operation, set current to null, restore current operation. var original = op.UndoLocalSourceExecuteIStoreTransactionScope; op.UndoLocalSourceExecuteIStoreTransactionScope = null; try { return(op.UndoLocalSourceExecute(ts)); } finally { op.UndoLocalSourceExecuteIStoreTransactionScope = original; } } }; return(op); } }; ShardMapManager smm = new ShardMapManager( new SqlShardMapManagerCredentials(Globals.ShardMapManagerConnectionString), new SqlStoreConnectionFactory(), sof, new CacheStore(), ShardMapManagerLoadPolicy.Lazy, new RetryPolicy(1, TimeSpan.Zero, TimeSpan.Zero, TimeSpan.Zero), RetryBehavior.DefaultRetryBehavior); ShardMap sm = smm.GetShardMap(ShardMapTests.s_defaultShardMapName); Assert.IsNotNull(sm); ShardLocation sl = new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, ShardMapTests.s_shardedDBs[0]); Shard sNew = sm.CreateShard(sl); Assert.IsNotNull(sNew); bool storeOperationFailed = false; try { sm.DeleteShard(sNew); } catch (ShardManagementException sme) { Assert.AreEqual(ShardManagementErrorCategory.ShardMap, sme.ErrorCategory); Assert.AreEqual(ShardManagementErrorCode.StorageOperationFailure, sme.ErrorCode); storeOperationFailed = true; } Assert.IsTrue(storeOperationFailed); // verify that the shard exists in store. Shard sValidate = sm.GetShard(sl); Assert.IsNotNull(sValidate); // Obtain the pending operations. var pendingOperations = ShardMapperTests.GetPendingStoreOperations(); Assert.AreEqual(pendingOperations.Count(), 1); shouldThrow = false; storeOperationFailed = false; try { sm.DeleteShard(sNew); } catch (ShardManagementException) { storeOperationFailed = true; } Assert.IsFalse(storeOperationFailed); Assert.AreEqual(0, sm.GetShards().Count()); }
public void CreateShardAbortGSM() { int retryCount = 0; EventHandler <RetryingEventArgs> eventHandler = (sender, arg) => { retryCount++; }; ShardMapManager smm = new ShardMapManager( new SqlShardMapManagerCredentials(Globals.ShardMapManagerConnectionString), new SqlStoreConnectionFactory(), new StubStoreOperationFactory() { CallBase = true, CreateAddShardOperationShardMapManagerIStoreShardMapIStoreShard = (_smm, _sm, _s) => new NTimeFailingAddShardOperation(10, _smm, _sm, _s) }, new CacheStore(), ShardMapManagerLoadPolicy.Lazy, new RetryPolicy(5, TimeSpan.Zero, TimeSpan.Zero, TimeSpan.Zero), RetryBehavior.DefaultRetryBehavior); ShardMap sm = smm.GetShardMap(ShardMapTests.s_defaultShardMapName); Assert.IsNotNull(sm); ShardLocation sl = new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, ShardMapTests.s_shardedDBs[0]); bool storeOperationFailed = false; smm.ShardMapManagerRetrying += eventHandler; try { Shard sNew = sm.CreateShard(sl); Assert.IsNotNull(sNew); } catch (ShardManagementException sme) { Assert.AreEqual(ShardManagementErrorCategory.ShardMap, sme.ErrorCategory); Assert.AreEqual(ShardManagementErrorCode.StorageOperationFailure, sme.ErrorCode); storeOperationFailed = true; } smm.ShardMapManagerRetrying -= eventHandler; Assert.AreEqual(5, retryCount); Assert.IsTrue(storeOperationFailed); // verify that shard map does not have any shards. int count = 0; IEnumerable <Shard> sList = sm.GetShards(); using (IEnumerator <Shard> sEnum = sList.GetEnumerator()) { while (sEnum.MoveNext()) { count++; } } Assert.AreEqual(0, count); }
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 TestSimpleSelect(MultiShardExecutionPolicy policy) { // What we're doing: // Grab all rows from each test database. // Load them into a MultiShardDataReader. // Iterate through the rows and make sure that we have 9 total. // using (MultiShardConnection conn = new MultiShardConnection(_shardMap.GetShards(), MultiShardTestUtils.ShardConnectionString)) { using (MultiShardCommand cmd = conn.CreateCommand()) { cmd.CommandText = "SELECT dbNameField, Test_int_Field, Test_bigint_Field FROM ConsistentShardedTable"; cmd.ExecutionOptions = MultiShardExecutionOptions.IncludeShardNameColumn; cmd.ExecutionPolicy = policy; using (MultiShardDataReader sdr = cmd.ExecuteReader()) { int recordsRetrieved = 0; Logger.Log("Starting to get records"); while (sdr.Read()) { recordsRetrieved++; string dbNameField = sdr.GetString(0); int testIntField = sdr.GetFieldValue <int>(1); Int64 testBigIntField = sdr.GetFieldValue <Int64>(2); string shardIdPseudoColumn = sdr.GetFieldValue <string>(3); string logRecord = string.Format( "RecordRetrieved: dbNameField: {0}, TestIntField: {1}, TestBigIntField: {2}, shardIdPseudoColumnField: {3}, RecordCount: {4}", dbNameField, testIntField, testBigIntField, shardIdPseudoColumn, recordsRetrieved); Logger.Log(logRecord); Debug.WriteLine(logRecord); } sdr.Close(); Assert.AreEqual(recordsRetrieved, 9); } } } }
public void MyTestInitialize() { _shardMap = MultiShardTestUtils.CreateAndGetTestShardMap(); _shardConnection = new MultiShardConnection(_shardMap.GetShards(), MultiShardTestUtils.ShardConnectionString); }
/// <summary> /// Helper function to add a new shard to given shard map. /// </summary> /// <param name="sm"></param> private void AddShardToShardMap(ShardMap sm) { IEnumerable<Shard> existingShards = sm.GetShards(); // get list of shard locations that are not already added to this shard map. List<string> availableLocationList = (from dbName in ShardMapManagerLoadTests.s_shardedDBs where !existingShards.Select(s => s.Location.Database).ToList().Contains(dbName) select dbName).ToList(); if (availableLocationList.Count > 0) { ShardLocation sl = new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, availableLocationList[_r.Next(availableLocationList.Count)]); Debug.WriteLine("Trying to add shard at location {0} to shard map {1}", sl, sm); ShardCreationInfo si = new ShardCreationInfo(sl, ShardStatus.Online); Shard newShard = sm.CreateShard(si); } }
/// <summary> /// Helper function to select a random shard for specified shard map. /// </summary> /// <param name="sm">Shard map to get shard.</param> /// <returns>Shard from specified shard map.</returns> private Shard GetRandomOnlineShardFromShardMap(ShardMap sm) { List<Shard> shardList = sm.GetShards().Where(s => s.Status == ShardStatus.Online).ToList(); if (shardList.Count > 0) return shardList[_r.Next(shardList.Count)]; else return null; }