bool UpdateProperty(BufferedReceiveMessageProperty property, ReceiveContext receiveContext, int channelKey, string bookmarkName, BufferedReceiveState state)
        {
            // If there's data already there make sure the state is allowed
            if (property.UserState == null)
            {
                property.UserState = new PropertyData()
                {
                    ReceiveContext = receiveContext,
                    ChannelKey     = channelKey,
                    BookmarkName   = bookmarkName,
                    State          = state
                };
            }
            else
            {
                PropertyData data = (PropertyData)property.UserState;

                // We should not buffer twice at the same state
                if (data.State == state)
                {
                    return(false);
                }

                data.State = state;
            }

            return(true);
        }
        public bool BufferReceive(OperationContext operationContext, ReceiveContext receiveContext, string bookmarkName, BufferedReceiveState state, bool retry)
        {
            bool flag = false;
            BufferedReceiveMessageProperty property = null;

            if (BufferedReceiveMessageProperty.TryGet(operationContext.IncomingMessageProperties, out property))
            {
                CorrelationMessageProperty property = null;
                if (!CorrelationMessageProperty.TryGet(operationContext.IncomingMessageProperties, out property))
                {
                    return(flag);
                }
                EventHandler handler     = null;
                InstanceKey  instanceKey = property.CorrelationKey;
                int          channelKey  = operationContext.Channel.GetHashCode();
                if (!this.throttle.Acquire(channelKey))
                {
                    return(flag);
                }
                try
                {
                    if (!this.UpdateProperty(property, receiveContext, channelKey, bookmarkName, state))
                    {
                        return(flag);
                    }
                    if (handler == null)
                    {
                        handler = delegate(object sender, EventArgs e) {
                            lock (this.thisLock)
                            {
                                if (this.bufferedProperties.ContainsKey(instanceKey) && this.bufferedProperties[instanceKey].Remove(property))
                                {
                                    try
                                    {
                                        property.RequestContext.DelayClose(false);
                                        property.RequestContext.Abort();
                                    }
                                    catch (Exception exception)
                                    {
                                        if (Fx.IsFatal(exception))
                                        {
                                            throw;
                                        }
                                    }
                                    this.throttle.Release(channelKey);
                                }
                            }
                        };
                    }
                    receiveContext.Faulted += handler;
                    lock (this.thisLock)
                    {
                        if (receiveContext.State != ReceiveContextState.Received)
                        {
                            return(flag);
                        }
                        bool flag2 = false;
                        if (retry)
                        {
                            property.RequestContext.DelayClose(true);
                            property.RegisterForReplay(operationContext);
                            property.ReplayRequest();
                            property.Notification.NotifyInvokeReceived(property.RequestContext.InnerRequestContext);
                            flag2 = true;
                        }
                        else
                        {
                            ReadOnlyCollection <BookmarkInfo> bookmarksForInstance = this.host.DurableInstanceManager.PersistenceProviderDirectory.GetBookmarksForInstance(instanceKey);
                            if (bookmarksForInstance != null)
                            {
                                for (int i = 0; i < bookmarksForInstance.Count; i++)
                                {
                                    BookmarkInfo info = bookmarksForInstance[i];
                                    if (info.BookmarkName == bookmarkName)
                                    {
                                        property.RequestContext.DelayClose(true);
                                        property.RegisterForReplay(operationContext);
                                        property.ReplayRequest();
                                        property.Notification.NotifyInvokeReceived(property.RequestContext.InnerRequestContext);
                                        flag2 = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if (!flag2)
                        {
                            List <BufferedReceiveMessageProperty> list;
                            if (!this.bufferedProperties.TryGetValue(instanceKey, out list))
                            {
                                list = new List <BufferedReceiveMessageProperty>();
                                this.bufferedProperties.Add(instanceKey, list);
                            }
                            property.RequestContext.DelayClose(true);
                            property.RegisterForReplay(operationContext);
                            list.Add(property);
                        }
                        else
                        {
                            this.throttle.Release(channelKey);
                        }
                        return(true);
                    }
                }
                finally
                {
                    if (!flag)
                    {
                        this.throttle.Release(channelKey);
                    }
                }
            }
            return(flag);
        }
        public bool BufferReceive(OperationContext operationContext, ReceiveContext receiveContext, string bookmarkName, BufferedReceiveState state, bool retry)
        {
            Fx.Assert(receiveContext != null, "ReceiveContext must be present in order to perform buffering");

            bool success = false;

            BufferedReceiveMessageProperty property = null;

            if (BufferedReceiveMessageProperty.TryGet(operationContext.IncomingMessageProperties, out property))
            {
                CorrelationMessageProperty correlation = null;
                if (CorrelationMessageProperty.TryGet(operationContext.IncomingMessageProperties, out correlation))
                {
                    InstanceKey instanceKey = correlation.CorrelationKey;
                    int         channelKey  = operationContext.Channel.GetHashCode();
                    if (this.throttle.Acquire(channelKey))
                    {
                        try
                        {
                            // Tag the property with identifying data to be used during later processing
                            if (UpdateProperty(property, receiveContext, channelKey, bookmarkName, state))
                            {
                                // Cleanup if we are notified the ReceiveContext faulted underneath us
                                receiveContext.Faulted += delegate(object sender, EventArgs e)
                                {
                                    lock (this.thisLock)
                                    {
                                        if (this.bufferedProperties.ContainsKey(instanceKey))
                                        {
                                            if (this.bufferedProperties[instanceKey].Remove(property))
                                            {
                                                try
                                                {
                                                    property.RequestContext.DelayClose(false);
                                                    property.RequestContext.Abort();
                                                }
                                                catch (Exception exception)
                                                {
                                                    if (Fx.IsFatal(exception))
                                                    {
                                                        throw;
                                                    }

                                                    // ---- these exceptions as we are already on the error path
                                                }

                                                this.throttle.Release(channelKey);
                                            }
                                        }
                                    }
                                };

                                // Actual Buffering
                                lock (this.thisLock)
                                {
                                    // Optimistic state check in case we just raced with the receiveContext
                                    // faulting. If the receiveContext still faults after the state check, the above
                                    // cleanup routine will handle things correctly. In both cases, a double-release
                                    // of the throttle is protected.
                                    if (receiveContext.State == ReceiveContextState.Received)
                                    {
                                        bool found = false;
                                        // if the exception indicates retry-able (such as RetryException),
                                        // we will simply retry.  This happens when racing with abort and
                                        // WF informing the client to retry (BufferedReceiveManager is a
                                        // client in this case).
                                        if (retry)
                                        {
                                            property.RequestContext.DelayClose(true);
                                            property.RegisterForReplay(operationContext);
                                            property.ReplayRequest();
                                            property.Notification.NotifyInvokeReceived(property.RequestContext.InnerRequestContext);
                                            found = true;
                                        }
                                        else
                                        {
                                            ReadOnlyCollection <BookmarkInfo> bookmarks = this.host.DurableInstanceManager.PersistenceProviderDirectory.GetBookmarksForInstance(instanceKey);
                                            // Retry in case match the existing bookmark
                                            if (bookmarks != null)
                                            {
                                                for (int i = 0; i < bookmarks.Count; ++i)
                                                {
                                                    BookmarkInfo bookmark = bookmarks[i];
                                                    if (bookmark.BookmarkName == bookmarkName)
                                                    {
                                                        // Found it so retry...
                                                        property.RequestContext.DelayClose(true);
                                                        property.RegisterForReplay(operationContext);
                                                        property.ReplayRequest();
                                                        property.Notification.NotifyInvokeReceived(property.RequestContext.InnerRequestContext);
                                                        found = true;
                                                        break;
                                                    }
                                                }
                                            }
                                        }

                                        if (!found)
                                        {
                                            List <BufferedReceiveMessageProperty> properties;
                                            if (!this.bufferedProperties.TryGetValue(instanceKey, out properties))
                                            {
                                                properties = new List <BufferedReceiveMessageProperty>();
                                                this.bufferedProperties.Add(instanceKey, properties);
                                            }
                                            property.RequestContext.DelayClose(true);
                                            property.RegisterForReplay(operationContext);
                                            properties.Add(property);
                                        }
                                        else
                                        {
                                            this.throttle.Release(channelKey);
                                        }
                                        success = true;
                                    }
                                }
                            }
                        }
                        finally
                        {
                            if (!success)
                            {
                                this.throttle.Release(channelKey);
                            }
                        }
                    }
                }
            }

            return(success);
        }
 private bool UpdateProperty(BufferedReceiveMessageProperty property, ReceiveContext receiveContext, int channelKey, string bookmarkName, BufferedReceiveState state)
 {
     if (property.UserState == null)
     {
         PropertyData data = new PropertyData {
             ReceiveContext = receiveContext,
             ChannelKey     = channelKey,
             BookmarkName   = bookmarkName,
             State          = state
         };
         property.UserState = data;
     }
     else
     {
         PropertyData userState = (PropertyData)property.UserState;
         if (userState.State == state)
         {
             return(false);
         }
         userState.State = state;
     }
     return(true);
 }