public DurableInstanceContextBindingElement(BindingElement other)
            : base(other)
        {
            DurableInstanceContextBindingElement otherBindingElement = other as DurableInstanceContextBindingElement;

            if (otherBindingElement != null)
            {
                this.contextStoreLocation = otherBindingElement.contextStoreLocation;
                this.contextType          = otherBindingElement.contextType;

                if ((contextStoreLocation == null) ||
                    (contextStoreLocation.Trim().Length == 0))
                {
                    InitializeContextStoreLocation();
                }
                else
                {
                    // Throw if the specified contextStoreLocation is
                    // invalid.
                    if (!Directory.Exists(contextStoreLocation))
                    {
                        throw new InvalidOperationException(
                                  ResourceHelper.GetString(@"ExInvalidContextStorePath"));
                    }
                }
            }
            else
            {
                this.contextType = ContextType.MessageHeader;
                InitializeContextStoreLocation();
            }
        }
예제 #2
0
        public void InitializeInstanceContext(InstanceContext instanceContext, System.ServiceModel.Channels.Message message, IContextChannel channel)
        {
            //Look if the Client has given us a unique ID to add to this InstanceContext
            int    headerIndex = message.Headers.FindHeader(CustomHeader.HeaderName, CustomHeader.HeaderNamespace);
            String headerId    = null;

            if (headerIndex != -1)
            {
                headerId = message.Headers.GetHeader <string>(headerIndex);
            }

            if (headerId == null)
            {
                //If no header was sent by the Client, then create a new one and assign it to this InstanceContext.
                headerId = Guid.NewGuid().ToString();
                Utility.WriteMessageToConsole(String.Format(ResourceHelper.GetString("NoHeaderFound")));
            }

            Utility.WriteMessageToConsole(String.Format(ResourceHelper.GetString("InstanceContextAddedToCache"), headerId));

            //Add this to the Cache
            this.instanceContextCache[headerId] = instanceContext;

            //Register the Closing event of this InstancContext so it can be removed from the collection
            instanceContext.Closing += this.RemoveInstanceContext;

            IExtension <InstanceContext> customLeaseExtension =
                new CustomLeaseExtension(timeout, headerId);

            instanceContext.Extensions.Add(customLeaseExtension);
        }
예제 #3
0
        /// <summary>
        /// This implements a PerCall InstanceContextMode behavior. If a cached InstanceContext is not found
        /// then WCF will create a new one.
        /// </summary>
        public InstanceContext GetExistingInstanceContext(System.ServiceModel.Channels.Message message, IContextChannel channel)
        {
            //Per Session behavior
            //To implement a PerSession behavior (If underlyin binding supports it) where in all
            //methods from one ChannelFactory will be serviced by the same InstanceContext

            //Check if the incoming request has the InstanceContext id it wants to connect with.
            if (message.Headers.FindHeader(CustomHeader.HeaderName, CustomHeader.HeaderNamespace) != -1)
            {
                String sharingId = message.Headers.GetHeader <string>(CustomHeader.HeaderName, CustomHeader.HeaderNamespace);
                if (sharingId != null && instanceContextCache.ContainsKey(sharingId))
                {
                    Utility.WriteMessageToConsole(String.Format(ResourceHelper.GetString("InstanceContextLookup"), sharingId));
                    //Retrieve the InstanceContext from the map
                    InstanceContext context = instanceContextCache[sharingId];
                    if (context != null)
                    {
                        //Before returning, stop the timer on this InstanceContext
                        CustomLeaseExtension extension = context.Extensions.Find <CustomLeaseExtension>();
                        Utility.WriteMessageToConsole(String.Format(ResourceHelper.GetString("StopInstanceContextIdleTimer"), sharingId));
                        extension.StopTimer();

                        Utility.WriteMessageToConsole(ResourceHelper.GetString("CachedInstanceContextFound"));
                        return(instanceContextCache[sharingId]);
                    }
                }
            }

            //No existing InstanceContext was found so return null and WCF will create a new one.
            return(null);
        }
예제 #4
0
        public static IStorageManager GetStorageManager(Type storageManagerType)
        {
            IStorageManager storageManager = null;

            if (storageManagerType == null)
            {
                return(new SqlServerStorageManager());
            }
            else
            {
                object obj = Activator.CreateInstance(storageManagerType);

                // Throw if the specified storage manager type does not
                // implement IStorageManager.
                if (obj is IStorageManager)
                {
                    storageManager = (IStorageManager)obj;
                }
                else
                {
                    throw new InvalidOperationException(
                              ResourceHelper.GetString("ExInvalidStorageManager"));
                }

                return(storageManager);
            }
        }
예제 #5
0
        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            // Create an instance of the ObjectPoolInstanceProvider.
            ObjectPoolingInstanceProvider instanceProvider = new ObjectPoolingInstanceProvider(description.ServiceType,
                                                                                               minPoolSize);

            // Forward the call if we created a ServiceThrottlingBehavior.
            if (this.throttlingBehavior != null)
            {
                ((IServiceBehavior)this.throttlingBehavior).ApplyDispatchBehavior(description, serviceHostBase);
            }

            // In case there was already a ServiceThrottlingBehavior (this.throttlingBehavior==null),
            // it should have initialized a single ServiceThrottle on all ChannelDispatchers.  As
            // we loop through the ChannelDispatchers, we verify that and modify the ServiceThrottle
            // to guard MaxPoolSize.
            ServiceThrottle throttle = null;

            foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher cd = cdb as ChannelDispatcher;
                if (cd != null)
                {
                    // Make sure there is exactly one throttle used by all endpoints.
                    // If there were others, we could not enforce MaxPoolSize.
                    if ((this.throttlingBehavior == null) && (this.maxPoolSize != Int32.MaxValue))
                    {
                        if (throttle == null)
                        {
                            throttle = cd.ServiceThrottle;
                        }
                        if (cd.ServiceThrottle == null)
                        {
                            throw new InvalidOperationException(ResourceHelper.GetString("ExNullThrottle"));
                        }
                        if (throttle != cd.ServiceThrottle)
                        {
                            throw new InvalidOperationException(ResourceHelper.GetString("ExDifferentThrottle"));
                        }
                    }

                    foreach (EndpointDispatcher ed in cd.Endpoints)
                    {
                        // Assign it to DispatchBehavior in each endpoint.
                        ed.DispatchRuntime.InstanceProvider = instanceProvider;
                    }
                }
            }

            // Set the MaxConcurrentInstances to limit the number of items that will
            // ever be requested from the pool.
            if ((throttle != null) && (throttle.MaxConcurrentInstances > this.maxPoolSize))
            {
                throttle.MaxConcurrentInstances = this.maxPoolSize;
            }
        }
예제 #6
0
 /// <summary>
 /// Timer elapsed event handler.
 /// </summary>
 void idleTimer_Elapsed(object sender, ElapsedEventArgs args)
 {
     lock (thisLock)
     {
         StopTimer();
         isIdle = true;
         Utility.WriteMessageToConsole(
             ResourceHelper.GetString("MsgLeaseExpired"));
         callback(owner);
     }
 }
예제 #7
0
        public void RemoveInstanceContext(object o, EventArgs args)
        {
            InstanceContext      context   = o as InstanceContext;
            CustomLeaseExtension extension = context.Extensions.Find <CustomLeaseExtension>();
            String id = (extension != null) ? extension.InstanceId : null;

            if (this.instanceContextCache[id] != null)
            {
                Utility.WriteMessageToConsole(String.Format(ResourceHelper.GetString("InstanceContextRemovedFromCache"), id));
                this.instanceContextCache.Remove(id);
            }
        }
예제 #8
0
        TChannel GetChannelWrapper(TChannel innerChannel)
        {
            if (innerChannel == null)
            {
                return(null);
            }

            if (typeof(TChannel) == typeof(IInputChannel))
            {
                return((TChannel)(object)new DurableInstanceContextInputChannel(this,
                                                                                contextType,
                                                                                (IInputChannel)innerChannel));
            }
            else if (typeof(TChannel) == typeof(IInputSessionChannel))
            {
                return((TChannel)(object)new DurableInstanceContextInputSessionChannel(this,
                                                                                       contextType,
                                                                                       (IInputSessionChannel)innerChannel));
            }
            else if (typeof(TChannel) == typeof(IReplyChannel))
            {
                return((TChannel)(object)new DurableInstanceContextReplyChannel(this,
                                                                                contextType,
                                                                                (IReplyChannel)innerChannel));
            }
            else if (typeof(TChannel) == typeof(IReplySessionChannel))
            {
                return((TChannel)(object)new DurableInstanceContextReplySessionChannel(
                           this,
                           contextType,
                           (IReplySessionChannel)innerChannel));
            }
            else if (typeof(TChannel) == typeof(IDuplexChannel))
            {
                return((TChannel)(object)new DurableInstanceContextDuplexChannel(this,
                                                                                 contextType,
                                                                                 (IDuplexChannel)innerChannel,
                                                                                 contextStoreLocation));
            }
            else if (typeof(TChannel) == typeof(IDuplexSessionChannel))
            {
                return((TChannel)(object)new DurableInstanceContextDuplexSessionChannel(
                           this,
                           contextType,
                           (IDuplexSessionChannel)innerChannel,
                           contextStoreLocation));
            }
            else
            {
                throw new NotSupportedException(
                          ResourceHelper.GetString("ExChannelNotSupported"));
            }
        }
예제 #9
0
        string GetConnectionString()
        {
            string connectionString =
                ConfigurationManager.AppSettings[DurableInstanceContextUtility.ConnectionString];

            if (connectionString == null)
            {
                throw new InvalidOperationException(
                          ResourceHelper.GetString("ExConnectionStringNotFound"));
            }

            return(connectionString);
        }
예제 #10
0
        public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            // Throw if the instance context mode is Single.
            ServiceBehaviorAttribute serviceBehavior =
                description.Behaviors.Find <ServiceBehaviorAttribute>();

            if (serviceBehavior != null &&
                serviceBehavior.InstanceContextMode == InstanceContextMode.Single)
            {
                throw new InvalidOperationException(
                          ResourceHelper.GetString("ExInvalidContext"));
            }
        }
        //If the context type is set to HttpCookie this
        //function verifies that the current binding
        //is using the HTTP transport.
        void ValidateTransport(CustomBinding binding)
        {
            if (this.contextType == ContextType.HttpCookie)
            {
                HttpTransportBindingElement httpTransport =
                    binding.Elements.Find <HttpTransportBindingElement>();

                if (httpTransport == null)
                {
                    throw new InvalidOperationException(
                              ResourceHelper.GetString("ExInvalidTransport"));
                }
            }
        }
예제 #12
0
        /// <summary>
        /// Puts an object back to the pool.
        /// </summary>
        /// <remarks>
        /// This method is invoked by WCF runtime.
        /// </remarks>
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            lock (poolLock)
            {
                // Check whether the object can be pooled.
                // Call the Deactivate method if possible.
                if (instance is IObjectControl)
                {
                    IObjectControl objectControl = (IObjectControl)instance;
                    objectControl.Deactivate();

                    if (objectControl.CanBePooled)
                    {
                        pool.Push(instance);

                        #if (DEBUG)
                        WritePoolMessage(
                            ResourceHelper.GetString("MsgObjectPooled"));
                        #endif
                    }
                    else
                    {
                        #if (DEBUG)
                        WritePoolMessage(
                            ResourceHelper.GetString("MsgObjectWasNotPooled"));
                        #endif
                    }
                }
                else
                {
                    pool.Push(instance);

                    #if (DEBUG)
                    WritePoolMessage(
                        ResourceHelper.GetString("MsgObjectPooled"));
                    #endif
                }

                activeObjectsCount--;

                if (activeObjectsCount == 0)
                {
                    idleTimer.Start();
                }
            }

            availableCount.Release(1);
        }
        void IInstanceProvider.ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            lock (poolLock)
            {
                pool.Push(instance);
                activeObjectsCount--;

                WritePoolMessage(ResourceHelper.GetString("MsgObjectPooled"));

                // When the service goes completely idle (no requests are being processed),
                // the idle timer is started
                if (activeObjectsCount == 0)
                {
                    idleTimer.Start();
                }
            }
        }
예제 #14
0
        /// <summary>
        /// Implements the logic for returning an object
        /// from the pool.
        /// </summary>
        private object GetObjectFromThePool()
        {
            bool didNotTimeout =
                availableCount.WaitOne(creationTimeout, true);

            if (didNotTimeout)
            {
                object obj = null;

                lock (poolLock)
                {
                    if (pool.Count != 0)
                    {
                        obj = pool.Pop();
                        activeObjectsCount++;
                    }
                    else if (pool.Count == 0)
                    {
                        if (activeObjectsCount < maxPoolSize)
                        {
                            obj = CreateNewPoolObject();
                            activeObjectsCount++;

                            #if (DEBUG)
                            WritePoolMessage(
                                ResourceHelper.GetString("MsgNewObject"));
                            #endif
                        }
                    }

                    idleTimer.Stop();
                }

                // Call the Activate method if possible.
                if (obj is IObjectControl)
                {
                    ((IObjectControl)obj).Activate();
                }

                return(obj);
            }

            throw new TimeoutException(
                      ResourceHelper.GetString("ExObjectCreationTimeout"));
        }
예제 #15
0
        public bool IsIdle(InstanceContext instanceContext)
        {
            lock (thisLock)
            {
                if (isIdle)
                {
                    Utility.WriteMessageToConsole(
                        ResourceHelper.GetString("MsgIdle"));
                }
                else
                {
                    Utility.WriteMessageToConsole(
                        ResourceHelper.GetString("MsgNotIdle"));
                }

                bool idleCopy = isIdle;
                isIdle = false;
                return(idleCopy);
            }
        }
예제 #16
0
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            // Durable instancing could not be used with
            // singleton instancing.
            ServiceBehaviorAttribute serviceBehavior =
                serviceDescription.Behaviors.Find <ServiceBehaviorAttribute>();

            if (serviceBehavior != null &&
                serviceBehavior.InstanceContextMode == InstanceContextMode.Single)
            {
                throw new InvalidOperationException(
                          ResourceHelper.GetString("ExSingeltonInstancingNotSupported"));
            }

            // Use the StorageManagerFactory to create an instance of a
            // storage manager.
            IStorageManager storageManager =
                StorageManagerFactory.GetStorageManager(storageManagerType);

            InstanceContextInitializer contextInitializer =
                new InstanceContextInitializer(storageManager);

            InstanceProvider instanceProvider =
                new InstanceProvider(serviceDescription.ServiceType);

            foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher cd = cdb as ChannelDispatcher;

                if (cd != null)
                {
                    foreach (EndpointDispatcher ed in cd.Endpoints)
                    {
                        ed.DispatchRuntime.InstanceContextInitializers.Add(contextInitializer);
                        ed.DispatchRuntime.InstanceProvider = instanceProvider;
                    }
                }
            }
        }
예제 #17
0
        //Reads the durable instance context id from the incoming
        //messages.
        protected string ReadContextId(Message message)
        {
            IContextManager contextManager =
                ContextManagerFactory.CreateContextManager(contextType,
                                                           this.contextStoreLocation,
                                                           this.endpointAddress);

            string contextId = contextManager.ReadContext(message);

            if (contextId == null)
            {
                throw new CommunicationException(
                          ResourceHelper.GetString("ExContextNotFound"));
            }

            // Add the context id to the properties collection of the Message.
            // This way we can pass the context id to the service model layer in a
            // consistent manner regardless of the context type.
            message.Properties.Add(DurableInstanceContextUtility.ContextIdProperty, contextId);

            return(contextId);
        }
예제 #18
0
        void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            if (this.maxPoolSize < this.minPoolSize)
            {
                throw new InvalidOperationException(ResourceHelper.GetString("ExMinLargerThanMax"));
            }

            // throw if the instance context mode is Single
            ServiceBehaviorAttribute serviceBehavior = description.Behaviors.Find <ServiceBehaviorAttribute>();

            if (serviceBehavior != null &&
                serviceBehavior.InstanceContextMode == InstanceContextMode.Single)
            {
                throw new InvalidOperationException(ResourceHelper.GetString("ExInvalidContext"));
            }

            // We need ServiceThrottlingBehavior to run before us, because it properly
            // initializes the ServiceThrottle property of the endpoints.  If there is
            // no ServiceThrottlingBehavior, we will create one and run it ourselves.
            // If there is one, we validate that it comes before us.
            int throttlingIndex = this.GetBehaviorIndex(description, typeof(ServiceThrottlingBehavior));

            if (throttlingIndex == -1)
            {
                this.throttlingBehavior = new ServiceThrottlingBehavior();
                this.throttlingBehavior.MaxConcurrentInstances = this.MaxPoolSize;

                // Forward the call if we created a ServiceThrottlingBehavior.
                ((IServiceBehavior)this.throttlingBehavior).Validate(description, serviceHostBase);
            }
            else
            {
                int poolingIndex = this.GetBehaviorIndex(description, typeof(ObjectPoolingAttribute));
                if (poolingIndex < throttlingIndex)
                {
                    throw new InvalidOperationException(ResourceHelper.GetString("ExThrottleBeforePool"));
                }
            }
        }
        // Clean up procedure
        void idleTimer_Elapsed(object sender, ElapsedEventArgs args)
        {
            idleTimer.Stop();

            lock (poolLock)
            {
                if (activeObjectsCount == 0)
                {
                    while (pool.Count > minPoolSize)
                    {
                        WritePoolMessage(ResourceHelper.GetString("MsgObjectRemoving"));

                        object removedItem = pool.Pop();

                        if (removedItem is IDisposable)
                        {
                            ((IDisposable)removedItem).Dispose();
                        }
                    }
                }
            }
        }
        object IInstanceProvider.GetInstance(InstanceContext instanceContext, Message message)
        {
            object obj = null;

            lock (poolLock)
            {
                if (pool.Count > 0)
                {
                    obj = pool.Pop();
                }
                else
                {
                    obj = CreateNewPoolObject();
                }
                activeObjectsCount++;
            }

            WritePoolMessage(ResourceHelper.GetString("MsgNewObject"));

            idleTimer.Stop();

            return(obj);
        }
예제 #21
0
        /// <summary>
        /// Clean up procedure.
        /// </summary>
        void idleTimer_Elapsed(object sender, ElapsedEventArgs args)
        {
            idleTimer.Stop();

            lock (poolLock)
            {
                if (activeObjectsCount == 0)
                {
                    // Remove the surplus objects.
                    if (pool.Count > minPoolSize)
                    {
                        while (pool.Count != minPoolSize)
                        {
                            #if (DEBUG)
                            WritePoolMessage(
                                ResourceHelper.GetString("MsgObjectRemoving"));
                            #endif

                            object removedItem = pool.Pop();

                            if (removedItem is IDisposable)
                            {
                                ((IDisposable)removedItem).Dispose();
                            }
                        }
                    }
                    else if (pool.Count < minPoolSize)
                    {
                        // Reinitialize the missing objects.
                        while (pool.Count != minPoolSize)
                        {
                            pool.Push(CreateNewPoolObject());
                        }
                    }
                }
            }
        }
        protected override void DeserializeElement(XmlReader reader,
                                                   bool serializeCollectionKey)
        {
            base.DeserializeElement(reader, serializeCollectionKey);
            string attributeValue;

            attributeValue =
                reader.GetAttribute(DurableInstanceContextUtility.ContextStoreLocation);

            if (attributeValue != null)
            {
                this.contextStoreLocation = attributeValue;
                attributeValue            = null;
            }

            attributeValue =
                reader.GetAttribute(DurableInstanceContextUtility.ContextType);

            if (attributeValue != null)
            {
                switch (attributeValue)
                {
                case DurableInstanceContextUtility.HttpCookie:
                    this.contextType = ContextType.HttpCookie;
                    break;

                case DurableInstanceContextUtility.MessageHeader:
                    this.contextType = ContextType.MessageHeader;
                    break;

                default:
                    throw new InvalidOperationException(
                              ResourceHelper.GetString(@"ExInvalidContextType"));
                }
            }
        }
예제 #23
0
        //Returns a new context id. This method initially tries to
        //read the context id from an existing file. If the context
        //id is available this simply returns that. Otherwise this creates
        //a new context id (Guid) and returns it. This also saves the newly
        //created context id into a file whose file name is created
        //according to the endpoint address.
        protected string GetContextId()
        {
            // Build the file name.
            string fileName = this.endpointAddress.ToString();

            ReplaceInvalidChars(ref fileName);
            fileName = string.Format(CultureInfo.InvariantCulture, @"{0}.txt", fileName);

            string absFilePath = string.Format(CultureInfo.InvariantCulture, @"{0}\{1}", this.contextStoreLocation,
                                               fileName);

            // Synchronize access to this file using a mutex.
            Mutex fileMutex = new Mutex(false, fileName);

            fileMutex.WaitOne();

            string contextId = null;

            if (File.Exists(absFilePath))
            {
                // Try to read the content from the file.
                using (StreamReader textReader = File.OpenText(absFilePath))
                {
                    if (textReader != null)
                    {
                        contextId = textReader.ReadLine();
                        try
                        {
                            Guid guid = new Guid(contextId);
                        }
                        catch (Exception e)
                        {
                            throw new InvalidOperationException(
                                      ResourceHelper.GetString("ExInvalidContextId"),
                                      e);
                        }
                    }
                }
            }
            else
            {
                // Create a new context id and write it to a file in the
                // directory specified by contextStorageLocation.
                contextId = Guid.NewGuid().ToString();
                UTF8Encoding encoding = new UTF8Encoding(true, false);
                byte[]       buffer   = encoding.GetBytes(contextId);

                // Do not other processes to access this file until
                // we are done.
                FileStream fs = new FileStream(absFilePath,
                                               FileMode.Create, FileAccess.ReadWrite,
                                               FileShare.None);

                fs.Write(buffer, 0, buffer.Length);
                fs.Close();
            }

            // Release the mutex.
            fileMutex.ReleaseMutex();
            return(contextId);
        }
        protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
        {
            TChannel innerChannel =
                innerChannelFactory.CreateChannel(address, via);

            if (typeof(TChannel) ==
                typeof(IOutputChannel))
            {
                return((TChannel)(object)new DurableInstanceContextOutputChannel(
                           this,
                           contextType,
                           (IOutputChannel)innerChannel,
                           contextStoreLocation));
            }
            else if (typeof(TChannel) ==
                     typeof(IOutputSessionChannel))
            {
                return((TChannel)(object)new DurableInstanceContextOutputSessionChannel(
                           this,
                           contextType,
                           (IOutputSessionChannel)innerChannel,
                           contextStoreLocation));
            }
            else if (typeof(TChannel) ==
                     typeof(IRequestChannel))
            {
                return((TChannel)(object)new DurableInstanceContextRequestChannel(
                           this,
                           contextType,
                           (IRequestChannel)innerChannel,
                           contextStoreLocation));
            }
            else if (typeof(TChannel) ==
                     typeof(IRequestSessionChannel))
            {
                return((TChannel)(object)new DurableInstanceContextRequestSessionChannel(
                           this,
                           contextType,
                           (IRequestSessionChannel)innerChannel,
                           contextStoreLocation));
            }
            else if (typeof(TChannel) ==
                     typeof(IDuplexChannel))
            {
                return((TChannel)(object)new DurableInstanceContextDuplexChannel(
                           this,
                           contextType,
                           (IDuplexChannel)innerChannel,
                           contextStoreLocation));
            }
            else if (typeof(TChannel) ==
                     typeof(IDuplexSessionChannel))
            {
                return((TChannel)(object)new DurableInstanceContextDuplexSessionChannel(
                           this,
                           contextType,
                           (IDuplexSessionChannel)innerChannel,
                           contextStoreLocation));
            }
            else
            {
                throw new NotSupportedException(
                          ResourceHelper.GetString("ExChannelNotSupported"));
            }
        }