Example #1
0
        private object ExecuteTest(string methodName, int numberOfExpectedWriteLocks, int numberOfExpectedReadLocks, object[] inParams)
        {
            object[]             outParams            = null;
            ReplicableMethodInfo replicableMethodInfo = ReplicationWithLockingTests.TypeInfo.ReplicableMethodInfos[methodName][0];

            ReplicationWithLockingTests.StateReplicator.ReplicableMethodInfo       = replicableMethodInfo;
            ReplicationWithLockingTests.StateReplicator.NumberOfExpectedWriteLocks = numberOfExpectedWriteLocks;
            ReplicationWithLockingTests.StateReplicator.NumberOfExpectedReadLocks  = numberOfExpectedReadLocks;
            return(replicableMethodInfo.Invoke(ReplicationWithLockingTests.Context, this.empty, this.empty, ReplicationWithLockingTests.ProgramInstance, replicableMethodInfo.Methods[0], inParams, out outParams));
        }
        private void InvokeProcessRequestAsync <TRequestType, TResult>(TaskCompletionSource <TResult> taskProducer, StatefulServiceExecutionContext executionContext, string methodName, Tuple <Type, Type[], object[]> methodParams)
        {
            Exception exception = null;

            try
            {
                if (!typeof(IProcessHttpRequest).IsAssignableFrom(typeof(TRequestType)) &&
                    !typeof(IProcessTcpRequest).IsAssignableFrom(typeof(TRequestType)))
                {
                    taskProducer.SetException(new NotSupportedException("Method not supported by the server"));
                    return;
                }

                // Get Session Information
                StatefulProgramInstance instance = null;
                DateTime            expiryTime;
                IComparable         sessionId;
                object              sessionObj          = null;
                HttpListenerContext httpListenerContext = methodParams.Item3[methodParams.Item3.Length - 1] as HttpListenerContext;
                if (httpListenerContext != null)
                {
                    sessionObj = httpListenerContext.Request;
                }
                else
                {
                    // For TCP we smuggle the headers in IDictionary<string, string> passed via asyncState
                    StreamWrapper streamWrapper = methodParams.Item3[methodParams.Item3.Length - 1] as StreamWrapper;
                    sessionObj = streamWrapper != null ? streamWrapper.UserData : null;
                }

                if (!StatefulServiceReplica <TInstance> .GetSessionInformation(sessionObj, out sessionId, out expiryTime))
                {
                    // TODO: We do not support session expiry currently
                    sessionId  = Helpers.GenerateUniqueId();
                    expiryTime = DateTime.UtcNow.AddYears(100);
                }
                else
                {
                    instance = this.instanceManager.GetInstance(sessionId);
                }

                // Create a new instance if necessary
                bool setSessionInformation = false;
                bool isExpired             = sessionId != null && DateTime.UtcNow > expiryTime;
                if (instance == null)
                {
                    this.CreateInstance(sessionId, null);
                    instance = this.instanceManager.GetInstance(sessionId);
                    setSessionInformation = true;
                }

                Action <Task> processRequestContinuation = delegate(Task task)
                {
                    this.Invoke <StatefulServiceExecutionContext>(
                        (cec) =>
                    {
                        Exception exception1 = null;
                        try
                        {
                            if (setSessionInformation)
                            {
                                if (httpListenerContext != null)
                                {
                                    sessionObj = httpListenerContext.Response;
                                }
                                else
                                {
                                    // For TCP we smuggle the headers in asyncObject
                                    sessionObj = (IDictionary <string, string>)methodParams.Item3[methodParams.Item3.Length - 1];
                                }

                                StatefulServiceReplica <TInstance> .SetSessionInformation(sessionObj, sessionId, expiryTime);
                            }

                            if (!task.IsFaulted)
                            {
                                // Get the result from either the http task or task returned by Replicable method invocation.
                                object result = null;
                                if (typeof(IProcessTcpRequest).IsAssignableFrom(typeof(TRequestType)))
                                {
                                    Task <Stream> tcpResponseTask = task as Task <Stream>;
                                    if (tcpResponseTask != null)
                                    {
                                        result = tcpResponseTask.Result;
                                    }
                                    else
                                    {
                                        Task <object> taskWithObj = task as Task <object>;
                                        result = (Stream)taskWithObj.Result;
                                    }
                                }

                                taskProducer.SetResult((TResult)result);
                            }
                            else
                            {
                                exception1 = task.Exception.InnerException ?? task.Exception;
                            }

                            if (isExpired)
                            {
                                this.DeleteInstance(sessionId);
                            }
                        }
                        catch (Exception e)
                        {
                            AppTrace.TraceException(e, "StatefulServiceReplicaT.InvokeProcessRequestAsync");
                            exception1 = e;
                        }
                        finally
                        {
                            if (exception1 != null)
                            {
                                taskProducer.SetException(exception1);
                            }
                        }
                    });
                };

                if (instance != null && !isExpired)
                {
                    IEnumerable <ReplicableMethodInfo> matchingMethods = null;
                    instance.TypeInfo.TryGetMatchingMethod("ProcessRequestAsync", methodParams.Item1, methodParams.Item2, out matchingMethods);
                    int matchingMethodCount = matchingMethods != null?matchingMethods.Count() : 0;

                    if (matchingMethodCount == 1 && matchingMethods.First().Type == ReplicableMethodInfo.MethodType.AsyncTask)
                    {
                        ReplicableMethodInfo             methodInfo          = matchingMethods.First();
                        Task <Tuple <object, object[]> > asyncInvocationTask = instance.InvokeAsync(methodInfo.Methods[0], methodParams.Item3);
                        asyncInvocationTask.Wait();
                        Task task = (Task)asyncInvocationTask.Result.Item1;
                        task.ContinueWith(processRequestContinuation);
                    }
                    else if (matchingMethodCount > 1)
                    {
                        exception = new AmbiguousMatchException(String.Format(CultureInfo.InvariantCulture, "Multiple methods with name '{0}' matching similar parameters were found", "ProcessRequestAsync"));
                    }
                    else if (typeof(IProcessHttpRequest).IsAssignableFrom(typeof(TRequestType)))
                    {
                        ((IProcessHttpRequest)instance.Instance).ProcessRequestAsync((HttpListenerContext)methodParams.Item3[0])
                        .ContinueWith(task => { processRequestContinuation(task); }, TaskContinuationOptions.ExecuteSynchronously);
                    }
                    else
                    {
                        ((IProcessTcpRequest)instance.Instance).ProcessRequestAsync((Stream)methodParams.Item3[0])
                        .ContinueWith(task => { processRequestContinuation(task); }, TaskContinuationOptions.ExecuteSynchronously);
                    }
                }
                else
                {
                    AppTrace.TraceMsg(TraceLogEventType.Warning, "StatefulServiceReplicaT.InvokeProcessRequestAsync", "Instance cannot be created for expired session cookie with session id '{0}'.", sessionId);
                    taskProducer.SetException(new InvalidOperationException("Instance expired. Service cannot process request"));
                }
            }
            catch (Exception e)
            {
                AppTrace.TraceException(e, "StatefulServiceReplicaT.InvokeProcessRequestAsync");
                exception = e;
            }
            finally
            {
                if (exception != null)
                {
                    taskProducer.SetException(exception);
                }
            }
        }