/// <summary> /// Each partition is assigned a new session manager and /// registered for the inbound session callback. /// </summary> /// <param name="instanceName"></param> /// <param name="partition"></param> void InitializeReliableSessions(Uri instanceName, PartitionRecord partition) { IReliableSessionManager sessionManager; switch (partition.PartitionType) { case PartitionKeyType.Singleton: sessionManager = new ReliableSessionManager(Guid.NewGuid(), 0, instanceName); break; case PartitionKeyType.StringKey: sessionManager = new ReliableSessionManager(Guid.NewGuid(), 0, instanceName, partition.StringPartitionPartitionKey); break; case PartitionKeyType.Int64Key: sessionManager = new ReliableSessionManager(Guid.NewGuid(), 0, instanceName, partition.Int64PartitionPartitionKey); break; default: throw new ArgumentOutOfRangeException(); } // Open session, register callbacks sessionManager.OpenAsync(new SessionAbortedCallBack(), new CancellationToken()).Wait(); Task <string> endpointResultTask = sessionManager.RegisterInboundSessionCallbackAsync( new InboundSessionCallback(partition), new CancellationToken()); partition.SessionManager = sessionManager; endpointResultTask.Wait(); partition.Endpoint = endpointResultTask.Result; }
/// <summary> /// /// </summary> /// <param name="suffix"></param> /// <returns></returns> public static string GetEndpoint(string suffix) { Uri dummySvcInstance = new Uri("fabric:/test/dummy/svcInstance/" + suffix); ReliableSessionManager dummySessionManager = new ReliableSessionManager(Guid.NewGuid(), 0, dummySvcInstance); LogHelper.Log("open dummy reliable session manager to register to discover endpoint"); dummySessionManager.OpenAsync(new SessionAbortedCallBack(), new CancellationToken()).Wait(); // not a real test -- don't run this! // SessionTest dummyTest = new SessionTest(0, 0, 0, 0); PartitionRecord dummyRecord = new PartitionRecord(dummySvcInstance, PartitionKeyType.Singleton, null, new IntegerPartitionKeyRange()); Task <string> dummyEndpointResultTask = dummySessionManager.RegisterInboundSessionCallbackAsync( new InboundSessionCallback(dummyRecord), new CancellationToken()); dummyEndpointResultTask.Wait(); return(dummyEndpointResultTask.Result); }
public InboundSessionCallback(PartitionRecord partitionRec) { this.myPartitionRecord = partitionRec; }
public void RandomTests_ParallelSessionsProfile() { try { Utility.WrapNativeSyncInvokeInMTA(() => { try { // Number of parallel sessions tests const int sessionCount = 100; // Instantiate multiple test sessions. SessionTest[] sessionTests = new SessionTest[sessionCount]; // Number of service instances const int instanceCount = 5; // Instantiate the required service instances. InstanceRecord[] instances = new InstanceRecord[instanceCount]; // Max number of partition per instance const int maxPartitionsPerInstance = 3; // If Partition type is int64 range, than use this to set the low value range const int int64PartitionKeyLowValMultiplier = 10000; // Initialize Service Instances and randomly allocate partitions for each. InitializeInstances(instances, true, maxPartitionsPerInstance); // Initialize Partitions and respective reliable sessions foreach (InstanceRecord instance in instances) { InitializePartitions(instance, true, new PartitionKeyType(), int64PartitionKeyLowValMultiplier); foreach (PartitionRecord partition in instance.Partitions) { this.InitializeReliableSessions(instance.InstanceName, partition); } } // Min Segment Size to set the boundaries for random segment size const int minSegmentSize = 100; // Max Segment Size to set the boundaries for random segment size const int maxSegmentSize = 499; // Min Message count to set the boundaries for random messages per session const int minMessageCountPerSession = 500; // Min Message count to set the boundaries for random messages per session const int maxMessageCountPerSession = 2500; // Wait for send Segment Wait In MilliSeconds Per Message const int waitPerMessage = 1000; // in milliseconds // Dictionary of unique pairs of inbound and outbound sessions Dictionary <string, string> checkForUniqueness = new Dictionary <string, string>(); // Initialize and Setup the session tests by randomly selecting message sizes and abort sessions. for (int i = 0; i < sessionCount; i++) { // Pick a random Source Partition and Target Partition and setup the session test between them PartitionRecord sourcePartitionRecord = GetRandomPartitionRecord(instances); PartitionRecord targetPartitionRecord = GetRandomPartitionRecord(instances); if (!String.Equals(sourcePartitionRecord.PartitionKey, targetPartitionRecord.PartitionKey)) { int segmentSize = RandGen.Next(minSegmentSize, maxSegmentSize); int messageCount = RandGen.Next(minMessageCountPerSession, maxMessageCountPerSession); SessionTest sessionTest = new SessionTest(segmentSize, messageCount, waitPerMessage, i); SetupSessionTest(sessionTest, sourcePartitionRecord, targetPartitionRecord); // Check if it's an unique test session combination before adding it to the test sessions. if ( checkForUniqueness.ContainsKey(sourcePartitionRecord.PartitionKey + targetPartitionRecord.PartitionKey)) { sessionTest.SkipTest = true; } else { checkForUniqueness.Add( sourcePartitionRecord.PartitionKey + targetPartitionRecord.PartitionKey, ""); LogHelper.Log("SessionId: {0}; Unique Partitions: s: {1} t: {2}", sessionTest.SessionId, sourcePartitionRecord.PartitionKey, targetPartitionRecord.PartitionKey); } sessionTests[i] = sessionTest; } else { i--; } } // Randomly start the tests in parallel const int maxTestDelay = sessionCount * 10; // Cache all run test() in an action delegate array with random delay starts Action[] testActions = sessionTests.Select( element => (element.SkipTest) ? null : new Action(() => element.RunTest(RandGen.Next() % maxTestDelay))) .ToArray(); // Create and start tasks for all non skipped tests Task[] tempTestTasksToRun = testActions .Where(element => element != null) .Select(element => Task.Factory.StartNew(element)).ToArray(); LogHelper.Log("Total number of Tests started = {0}", tempTestTasksToRun.Count()); Task.WaitAll(tempTestTasksToRun); LogHelper.Log("Total number of Tests {0} ran to completion.", tempTestTasksToRun.Count()); } catch (Exception ex) { LogHelper.Log("Caught Exception: {0}", ex); throw; } }, "MultipleParallelSessions"); } catch (Exception e) { VS.Assert.IsTrue(false, "Unexpected exception {0} during RandomTests_ParallelSessionsProfile()", e.ToString()); } }
/// <summary> /// Create and Initialize partitions for the given service instance . /// </summary> /// <param name="instance">Initialize partitions for this service instance</param> /// <param name="isRandomPartitionType">true - if the partition type is selected randomly - String or Int64</param> /// <param name="type">Set the partition type to this parameter, if isRandomPartitionType is false. /// Singleton type is not allowed as we will set this type if instance partitions count = 1</param> /// <param name="int64PartitionKeyLowValMultiplier"></param> static void InitializePartitions(InstanceRecord instance, bool isRandomPartitionType, PartitionKeyType type, int int64PartitionKeyLowValMultiplier) { // Singletone is not a valid type VS.Assert.IsTrue(type != PartitionKeyType.Singleton, "unexpected partition key type {0} in StartSessionManagersForServiceInstance", type); // Ensure we have a valid partitions count > 0 Uri instanceName = instance.InstanceName; int partitionCount = instance.CountOfPartitions; VS.Assert.IsTrue(partitionCount > 0, "unexpected partitionCount {0} in StartSessionManagersForServiceInstance", partitionCount); // singleton case if (partitionCount == 1) { PartitionRecord newPartition = new PartitionRecord( instanceName, PartitionKeyType.Singleton, null, new IntegerPartitionKeyRange()); instance.Partitions[0] = newPartition; return; } bool stringPartitions = false; // randomly allocate string or int64 partition type. if (isRandomPartitionType) { stringPartitions = (RandGen.Next() % 2) == 0; // decide if we have string or int64 partitions } else { if (type == PartitionKeyType.StringKey) { stringPartitions = true; } } for (int i = 0; i < partitionCount; i++) { PartitionRecord newPartition; if (stringPartitions) { // string partition key string partitionKey = i.ToString(CultureInfo.InvariantCulture); newPartition = new PartitionRecord( instanceName, PartitionKeyType.StringKey, partitionKey, new IntegerPartitionKeyRange()); instance.Partitions[i] = newPartition; LogHelper.Log("Created; Instance: {0} StringPartition: {1}", instanceName, partitionKey); } // numerical partition key -- single number range IntegerPartitionKeyRange partitionInt64Key = new IntegerPartitionKeyRange { IntegerKeyLow = i * int64PartitionKeyLowValMultiplier, IntegerKeyHigh = i * int64PartitionKeyLowValMultiplier + (RandGen.Next() % (int64PartitionKeyLowValMultiplier - 1)) }; newPartition = new PartitionRecord( instanceName, PartitionKeyType.Int64Key, null, partitionInt64Key); instance.Partitions[i] = newPartition; LogHelper.Log("Created; Instance: {0} Int64Partition: {1}-{2}", instanceName, partitionInt64Key.IntegerKeyLow, partitionInt64Key.IntegerKeyHigh); } }
/// <summary> /// Setup a session from source partition to target partition. /// </summary> /// <param name="sessionTest"></param> /// <param name="sourcePartition"></param> /// <param name="targetPartition"></param> private void SetupSessionTest(SessionTest sessionTest, PartitionRecord sourcePartition, PartitionRecord targetPartition) { VS.Assert.IsFalse(sourcePartition == targetPartition, "sourcePartition {0} equals targetPartition {1} in SetupSessionTests", sourcePartition, targetPartition); IReliableSessionManager sourceSessionManager = sourcePartition.SessionManager; Uri targetSvcInstance = targetPartition.InstanceName; string targetEndpoint = targetPartition.Endpoint; Task <IReliableMessagingSession> newOutboundSessionTask = null; bool testSkipped = false; try { // Setup the outbound session from source to target partition switch (targetPartition.PartitionType) { case PartitionKeyType.Singleton: newOutboundSessionTask = sourceSessionManager.CreateOutboundSessionAsync(targetSvcInstance, targetEndpoint, new CancellationToken()); break; case PartitionKeyType.StringKey: string targetStringKey = targetPartition.StringPartitionPartitionKey; newOutboundSessionTask = sourceSessionManager.CreateOutboundSessionAsync(targetSvcInstance, targetStringKey, targetEndpoint, new CancellationToken()); break; case PartitionKeyType.Int64Key: IntegerPartitionKeyRange targetInt64Key = targetPartition.Int64PartitionPartitionKey; long rangeSize = targetInt64Key.IntegerKeyHigh - targetInt64Key.IntegerKeyLow + 1; long targetPartitionNumber = targetInt64Key.IntegerKeyLow + (RandGen.Next() % rangeSize); newOutboundSessionTask = sourceSessionManager.CreateOutboundSessionAsync(targetSvcInstance, targetPartitionNumber, targetEndpoint, new CancellationToken()); break; } VS.Assert.IsNotNull(newOutboundSessionTask, "Null newOutboundSessionTask in SetupSessionTests"); newOutboundSessionTask.Wait(); sessionTest.OutboundSession = newOutboundSessionTask.Result; } catch (System.AggregateException e) { Exception inner = e.InnerException.InnerException; VS.Assert.AreEqual(inner.GetType(), typeof(System.Runtime.InteropServices.COMException), "Unexpected AggregateException {0} from CreateOutboundSessionAsync", inner.GetType().ToString()); // Due to random nature of source and target selection, it might be possible we create a duplicate selection. // in this case, we skip the test. System.Runtime.InteropServices.COMException realException = (System.Runtime.InteropServices.COMException)inner; uint hresult = (uint)realException.ErrorCode; uint expectedError = (uint)NativeTypes.FABRIC_ERROR_CODE.FABRIC_E_RELIABLE_SESSION_ALREADY_EXISTS; VS.Assert.AreEqual(expectedError, hresult, "Unexpected error HRESULT code {0} from CreateOutboundSessionAsync", hresult); testSkipped = true; LogHelper.Log("Test# skipped due to {0} exception ", hresult); } if (testSkipped) { sessionTest.SkipTest = true; } else { // initialize snapshot test and open the session for message communication. sessionTest.OutboundSession.OpenAsync(new CancellationToken()).Wait(); sessionTest.InboundSession = targetPartition.InboundSessions[sourcePartition.PartitionKey]; sessionTest.SnapshotOutbound = sessionTest.OutboundSession.GetDataSnapshot(); sessionTest.SnapshotInbound = sessionTest.InboundSession.GetDataSnapshot(); VS.Assert.IsFalse(sessionTest.InboundSession == sessionTest.OutboundSession, "sourcePartition equals targetPartition in SetupSessionTests"); } }