private void ApplySubscriptionIds(ISubscriptionIdMessage message, ChildSubscription child)
        {
            var ids       = message.GetSubscriptionIds();
            var initialId = child.Parent.Origin.TransactionId;
            var newIds    = child.Subscribers.CachedKeys.Concat(child.Parent.Alls.CachedKeys);

            if (ids.Length == 1 && ids[0] == initialId)
            {
                message.SetSubscriptionIds(newIds);
            }
            else
            {
                message.SetSubscriptionIds(ids.Where(id => id != initialId).Concat(newIds).ToArray());
            }
        }
        private SubscriptionSecurityAllMessage CheckSubscription(ref Message message)
        {
            lock (_sync)
            {
                if (_toFlush.Count > 0)
                {
                    var toFlush = _toFlush.CopyAndClear();

                    this.AddDebugLog("Flush {0} suspended.", toFlush.Length);

                    foreach (var msg in toFlush)
                    {
                        RaiseNewOutMessage(msg);
                    }
                }

                if (_parents.Count == 0)
                {
                    return(null);
                }

                if (message is ISubscriptionIdMessage subscrMsg && message is ISecurityIdMessage secIdMsg)
                {
                    foreach (var parentId in subscrMsg.GetSubscriptionIds())
                    {
                        if (_parents.TryGetValue(parentId, out var parent))
                        {
                            // parent subscription has security id (not null)
                            if (parent.Origin.SecurityId == secIdMsg.SecurityId)
                            {
                                return(null);
                            }

                            SubscriptionSecurityAllMessage allMsg = null;

                            if (!parent.Child.TryGetValue(secIdMsg.SecurityId, out var child))
                            {
                                allMsg = new SubscriptionSecurityAllMessage();

                                parent.Origin.CopyTo(allMsg);

                                allMsg.ParentTransactionId = parentId;
                                allMsg.TransactionId       = TransactionIdGenerator.GetNextId();
                                allMsg.SecurityId          = secIdMsg.SecurityId;

                                child = new ChildSubscription(allMsg.TypedClone());
                                child.Subscribers.Add(allMsg.TransactionId, child.Origin);

                                parent.Child.Add(secIdMsg.SecurityId, child);

                                allMsg.LoopBack(this, MessageBackModes.Chain);
                                _allChilds.Add(allMsg.TransactionId, RefTuple.Create(parentId, SubscriptionStates.Stopped));

                                this.AddDebugLog("New ALL map: {0}/{1} TrId={2}-{3}", child.Origin.SecurityId, child.Origin.DataType2, allMsg.ParentTransactionId, allMsg.TransactionId);
                            }

                            //var subscriptionIds = subscrMsg.GetSubscriptionIds().Where(i => i != parentId).Concat(child.Subscribers.Cache);
                            subscrMsg.SetSubscriptionIds(child.Subscribers.CachedKeys);

                            if (!child.State.IsActive())
                            {
                                child.Suspended.Add(message);
                                message = null;

                                this.AddDebugLog("ALL suspended: {0}/{1}, cnt={2}", child.Origin.SecurityId, child.Origin.DataType2, child.Suspended.Count);
                            }

                            return(allMsg);
                        }
                    }
                }
            }

            return(null);
        }
Exemplo n.º 3
0
        private SubscriptionSecurityAllMessage CheckSubscription(ref Message message)
        {
            lock (_sync)
            {
                if (_toFlush.Count > 0)
                {
                    var childs = _toFlush.CopyAndClear();

                    foreach (var child in childs)
                    {
                        this.AddDebugLog("ALL flush: {0}/{1}, cnt={2}", child.Origin.SecurityId, child.Origin.DataType2, child.Suspended.Count);

                        foreach (var msg in child.Suspended.CopyAndClear())
                        {
                            ApplySubscriptionIds(msg, child);
                            RaiseNewOutMessage((Message)msg);
                        }
                    }
                }

                if (_parents.Count == 0)
                {
                    return(null);
                }

                if (message is ISubscriptionIdMessage subscrMsg && message is ISecurityIdMessage secIdMsg)
                {
                    foreach (var parentId in subscrMsg.GetSubscriptionIds())
                    {
                        if (_parents.TryGetValue(parentId, out var parent))
                        {
                            // parent subscription has security id (not null)
                            if (parent.Origin.SecurityId == secIdMsg.SecurityId)
                            {
                                ApplySubscriptionIds(subscrMsg, parent, new[] { parent.Origin.TransactionId });
                                return(null);
                            }

                            SubscriptionSecurityAllMessage allMsg = null;

                            if (!parent.Child.TryGetValue(secIdMsg.SecurityId, out var child))
                            {
                                allMsg = new SubscriptionSecurityAllMessage();

                                parent.Origin.CopyTo(allMsg);

                                allMsg.ParentTransactionId = parentId;
                                allMsg.TransactionId       = TransactionIdGenerator.GetNextId();
                                allMsg.SecurityId          = secIdMsg.SecurityId;

                                child = new ChildSubscription(parent, allMsg.TypedClone());
                                child.Subscribers.Add(allMsg.TransactionId, child.Origin);

                                parent.Child.Add(secIdMsg.SecurityId, child);

                                allMsg.LoopBack(this, MessageBackModes.Chain);
                                _pendingLoopbacks.Add(allMsg.TransactionId, RefTuple.Create(parentId, SubscriptionStates.Stopped));

                                this.AddDebugLog("New ALL map: {0}/{1} TrId={2}-{3}", child.Origin.SecurityId, child.Origin.DataType2, allMsg.ParentTransactionId, allMsg.TransactionId);
                            }

                            if (!child.State.IsActive())
                            {
                                child.Suspended.Add(subscrMsg);
                                message = null;

                                this.AddDebugLog("ALL suspended: {0}/{1}, cnt={2}", child.Origin.SecurityId, child.Origin.DataType2, child.Suspended.Count);
                            }
                            else
                            {
                                ApplySubscriptionIds(subscrMsg, child);
                            }

                            return(allMsg);
                        }
                    }
                }
            }

            return(null);
        }
Exemplo n.º 4
0
 private void ApplySubscriptionIds(ISubscriptionIdMessage subscrMsg, ChildSubscription child)
 {
     ApplySubscriptionIds(subscrMsg, child.Parent, child.Subscribers.CachedKeys);
 }
        /// <inheritdoc />
        protected override void OnInnerAdapterNewOutMessage(Message message)
        {
            List <Message> extra = null;

            switch (message.Type)
            {
            case MessageTypes.Disconnect:
            case ExtendedMessageTypes.ReconnectingFinished:
            {
                ClearState();
                break;
            }

            case MessageTypes.SubscriptionResponse:
            {
                var responseMsg = (SubscriptionResponseMessage)message;

                if (responseMsg.Error != null)
                {
                    lock (_sync)
                    {
                        if (_parents.TryGetAndRemove(responseMsg.OriginalTransactionId, out var parent))
                        {
                            extra = new List <Message>();

                            foreach (var child in parent.Child.Values)
                            {
                                var childId = child.Origin.TransactionId;

                                if (_allChilds.TryGetValue(childId, out var tuple) && tuple.Second == SubscriptionStates.Stopped)
                                {
                                    // loopback subscription not yet come, so will reply later
                                    tuple.Second = SubscriptionStates.Error;
                                }
                                else
                                {
                                    extra.Add(new SubscriptionResponseMessage {
                                            OriginalTransactionId = childId, Error = responseMsg.Error
                                        });
                                }
                            }
                        }
                    }
                }

                break;
            }

            case MessageTypes.SubscriptionFinished:
            {
                var finishMsg = (SubscriptionFinishedMessage)message;

                lock (_sync)
                {
                    if (_parents.TryGetAndRemove(finishMsg.OriginalTransactionId, out var parent))
                    {
                        extra = new List <Message>();

                        foreach (var child in parent.Child.Values)
                        {
                            var childId = child.Origin.TransactionId;

                            if (_allChilds.TryGetValue(childId, out var tuple) && tuple.Second == SubscriptionStates.Stopped)
                            {
                                // loopback subscription not yet come, so will reply later
                                tuple.Second = SubscriptionStates.Finished;
                            }
                            else
                            {
                                extra.Add(new SubscriptionFinishedMessage {
                                        OriginalTransactionId = childId
                                    });
                            }
                        }
                    }
                }

                break;
            }

            default:
            {
                if (message is ISubscriptionIdMessage subscrMsg && message is ISecurityIdMessage secIdMsg)
                {
                    SubscriptionSecurityAllMessage allMsg = null;

                    bool CheckSubscription(long parentId)
                    {
                        lock (_sync)
                        {
                            if (_parents.TryGetValue(parentId, out var parent))
                            {
                                // parent subscription has security id (not null)
                                if (parent.Origin.SecurityId == secIdMsg.SecurityId)
                                {
                                    return(true);
                                }

                                if (!parent.Child.TryGetValue(secIdMsg.SecurityId, out var child))
                                {
                                    allMsg = new SubscriptionSecurityAllMessage();

                                    parent.Origin.CopyTo(allMsg);

                                    allMsg.ParentTransactionId = parentId;
                                    allMsg.TransactionId       = TransactionIdGenerator.GetNextId();
                                    allMsg.SecurityId          = secIdMsg.SecurityId;

                                    child = new ChildSubscription(allMsg.TypedClone());
                                    child.Subscribers.Add(allMsg.TransactionId, child.Origin);

                                    parent.Child.Add(secIdMsg.SecurityId, child);

                                    allMsg.LoopBack(this, MessageBackModes.Chain);
                                    _allChilds.Add(allMsg.TransactionId, RefTuple.Create(parentId, SubscriptionStates.Stopped));

                                    this.AddDebugLog("New ALL map: {0}/{1} TrId={2}-{3}", child.Origin.SecurityId, child.Origin.DataType2, allMsg.ParentTransactionId, allMsg.TransactionId);
                                }

                                //var subscriptionIds = subscrMsg.GetSubscriptionIds().Where(i => i != parentId).Concat(child.Subscribers.Cache);
                                subscrMsg.SetSubscriptionIds(child.Subscribers.CachedKeys);

                                if (!child.State.IsActive())
                                {
                                    child.Suspended.Add(message);
                                    message = null;

                                    this.AddDebugLog("ALL suspended: {0}/{1}, cnt={2}", child.Origin.SecurityId, child.Origin.DataType2, child.Suspended.Count);
                                }

                                return(true);
                            }
                        }

                        return(false);
                    }

                    foreach (var id in subscrMsg.GetSubscriptionIds())
                    {
                        if (CheckSubscription(id))
                        {
                            break;
                        }
                    }

                    if (allMsg != null)
                    {
                        base.OnInnerAdapterNewOutMessage(allMsg);
                    }
                }

                break;
            }
            }

            if (message != null)
            {
                base.OnInnerAdapterNewOutMessage(message);
            }

            if (extra != null)
            {
                foreach (var m in extra)
                {
                    base.OnInnerAdapterNewOutMessage(m);
                }
            }
        }