コード例 #1
0
        private void ApplySubscriptionIds(ISubscriptionIdMessage subscrMsg, ParentSubscription parent, long[] newIds)
        {
            var ids       = subscrMsg.GetSubscriptionIds();
            var initialId = parent.Origin.TransactionId;

            newIds = newIds.Concat(parent.Alls.CachedKeys);

            if (subscrMsg is ISecurityIdMessage secIdMsg && parent.NonAlls.TryGetValue(secIdMsg.SecurityId, out var set))
            {
                newIds = newIds.Concat(set.Cache);
            }

            if (ids.Length == 1 && ids[0] == initialId)
            {
                subscrMsg.SetSubscriptionIds(newIds);
            }
            else
            {
                subscrMsg.SetSubscriptionIds(ids.Where(id => id != initialId).Concat(newIds).ToArray());
            }
        }
コード例 #2
0
        /// <inheritdoc />
        protected override bool OnSendInMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Reset:
                ClearState();
                break;

            case MessageTypes.MarketData:
            {
                var mdMsg = (MarketDataMessage)message;

                if (mdMsg.IsSubscribe)
                {
                    var transId = mdMsg.TransactionId;

                    lock (_sync)
                    {
                        if (_allChilds.TryGetValue(transId, out var tuple))
                        {
                            if (tuple.Second != SubscriptionStates.Stopped)
                            {
                                if (tuple.Second == SubscriptionStates.Finished)
                                {
                                    RaiseNewOutMessage(new SubscriptionFinishedMessage
                                        {
                                            OriginalTransactionId = transId,
                                        });
                                }
                                else
                                {
                                    RaiseNewOutMessage(new SubscriptionResponseMessage
                                        {
                                            OriginalTransactionId = transId,
                                            Error = new InvalidOperationException(LocalizedStrings.SubscriptionInvalidState.Put(transId, tuple.Second)),
                                        });
                                }

                                return(true);
                            }

                            var child = _parents[tuple.First].Child[mdMsg.SecurityId];
                            child.State = SubscriptionStates.Active;
                            _toFlush.AddRange(child.Suspended.CopyAndClear());

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

                            RaiseNewOutMessage(new SubscriptionResponseMessage {
                                    OriginalTransactionId = transId
                                });
                            return(true);
                        }
                        else
                        {
                            if (!IsSecurityRequired(mdMsg.DataType2) || mdMsg.SecurityId == default)
                            {
                                var existing = _parents.FirstOrDefault(p => p.Value.Origin.DataType2 == mdMsg.DataType2).Value;

                                if (existing == null)
                                {
                                    var parent = new ParentSubscription(mdMsg.TypedClone());
                                    _parents.Add(transId, parent);

                                    // first child is parent
                                    _allChilds.Add(transId, RefTuple.Create(transId, SubscriptionStates.Stopped));

                                    // do not specify security cause adapter doesn't require it
                                    mdMsg.SecurityId = default;
                                    Extensions.AllSecurity.CopyEx(mdMsg, false);
                                }
                                else
                                {
                                    var childs = existing.Child;

                                    if (mdMsg.SecurityId != default)
                                    {
                                        var child = childs.SafeAdd(mdMsg.SecurityId, key => new ChildSubscription(mdMsg.TypedClone()));
                                        child.Subscribers.Add(transId, mdMsg.TypedClone());
                                    }
                                    else
                                    {
                                        foreach (var pair in childs)
                                        {
                                            pair.Value.Subscribers.Add(transId, mdMsg.TypedClone());
                                        }
                                    }

                                    RaiseNewOutMessage(new SubscriptionResponseMessage {
                                            OriginalTransactionId = transId
                                        });
                                    return(true);
                                }
                            }
                        }
                    }
                }
                else
                {
                    var childIds = ArrayHelper.Empty <long>();

                    lock (_sync)
                    {
                        if (_allChilds.TryGetAndRemove(mdMsg.OriginalTransactionId, out var tuple))
                        {
                            this.AddDebugLog("Sec ALL child {0} unsubscribe.", mdMsg.OriginalTransactionId);

                            Exception error = null;

                            if (!tuple.Second.IsActive())
                            {
                                error = new InvalidOperationException(LocalizedStrings.SubscriptionInvalidState.Put(mdMsg.OriginalTransactionId, tuple.Second));
                            }
                            else
                            {
                                var childs = _parents[tuple.First].Child;

                                var pair = childs.FirstOrDefault(p => p.Value.Origin.TransactionId == mdMsg.OriginalTransactionId);
                                var childSubscription = pair.Value;

                                if (childSubscription == null)
                                {
                                    error = new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(mdMsg.OriginalTransactionId));
                                }
                                else
                                {
                                    if (childSubscription.Subscribers.Remove(mdMsg.OriginalTransactionId))
                                    {
                                        if (childSubscription.Subscribers.Count == 0)
                                        {
                                            childs.Remove(pair.Key);
                                        }
                                    }
                                    else
                                    {
                                        error = new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(mdMsg.OriginalTransactionId));
                                    }
                                }
                            }

                            RaiseNewOutMessage(new SubscriptionResponseMessage
                                {
                                    OriginalTransactionId = mdMsg.TransactionId,
                                    Error = error,
                                });

                            return(true);
                        }

                        if (_parents.TryGetAndRemove(mdMsg.OriginalTransactionId, out var tuple2))
                        {
                            childIds = tuple2.Child.Values.Select(s => s.Origin.TransactionId).ToArray();
                        }
                    }

                    foreach (var id in childIds)
                    {
                        RaiseNewOutMessage(new SubscriptionFinishedMessage {
                                OriginalTransactionId = id
                            });
                    }
                }

                break;
            }
            }

            return(base.OnSendInMessage(message));
        }
コード例 #3
0
        /// <inheritdoc />
        protected override bool OnSendInMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Reset:
                ClearState();
                break;

            case MessageTypes.MarketData:
            {
                var mdMsg = (MarketDataMessage)message;

                if (mdMsg.IsSubscribe)
                {
                    var transId = mdMsg.TransactionId;

                    lock (_sync)
                    {
                        if (_pendingLoopbacks.TryGetAndRemove(transId, out var tuple))
                        {
                            if (tuple.Second != SubscriptionStates.Stopped)
                            {
                                if (tuple.Second == SubscriptionStates.Finished)
                                {
                                    RaiseNewOutMessage(new SubscriptionFinishedMessage
                                        {
                                            OriginalTransactionId = transId,
                                        });
                                }
                                else
                                {
                                    RaiseNewOutMessage(new SubscriptionResponseMessage
                                        {
                                            OriginalTransactionId = transId,
                                            Error = new InvalidOperationException(LocalizedStrings.SubscriptionInvalidState.Put(transId, tuple.Second)),
                                        });
                                }

                                return(true);
                            }

                            var parent = _parents[tuple.First];
                            var child  = parent.Child[mdMsg.SecurityId];
                            child.State = SubscriptionStates.Online;

                            if (child.Suspended.Count > 0)
                            {
                                _toFlush.Add(child);
                            }

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

                            _requests.Add(transId, Tuple.Create(parent, mdMsg.TypedClone()));

                            // for child subscriptions make online (or finished) immediatelly
                            RaiseNewOutMessage(mdMsg.CreateResponse());
                            //RaiseNewOutMessage(mdMsg.CreateResult());
                            return(true);
                        }
                        else
                        {
                            if (!IsSecurityRequired(mdMsg.DataType2) || mdMsg.SecurityId == default)
                            {
                                mdMsg = mdMsg.TypedClone();

                                var parent = _parents.FirstOrDefault(p => p.Value.Origin.DataType2 == mdMsg.DataType2).Value;

                                void AddSubscription()
                                {
                                    if (mdMsg.SecurityId == default)
                                    {
                                        // first ALL is initiator
                                        parent.Alls.Add(transId, mdMsg);
                                    }
                                    else
                                    {
                                        parent.NonAlls.SafeAdd(mdMsg.SecurityId).Add(transId);
                                    }

                                    _requests.Add(transId, Tuple.Create(parent, mdMsg));
                                }

                                if (parent == null)
                                {
                                    parent = new ParentSubscription(mdMsg);
                                    _parents.Add(transId, parent);

                                    AddSubscription();

                                    // do not specify security cause adapter doesn't require it
                                    mdMsg = mdMsg.TypedClone();
                                    Extensions.AllSecurity.CopyEx(mdMsg, false);
                                    message = mdMsg;

                                    this.AddInfoLog("Sec ALL {0} subscribing.", transId);
                                }
                                else
                                {
                                    AddSubscription();

                                    // for child subscriptions make online (or finished) immediatelly
                                    RaiseNewOutMessage(mdMsg.CreateResponse());
                                    //RaiseNewOutMessage(mdMsg.CreateResult());
                                    return(true);
                                }
                            }
                        }
                    }
                }
                else
                {
                    var originId = mdMsg.OriginalTransactionId;

                    lock (_sync)
                    {
                        var found = false;

                        if (!_requests.TryGetAndRemove(originId, out var tuple))
                        {
                            break;
                        }

                        //this.AddDebugLog("Sec ALL child {0} unsubscribe.", originId);

                        var parent  = tuple.Item1;
                        var request = tuple.Item2;
                        var secId   = request.SecurityId;
                        var transId = request.TransactionId;

                        if (parent.Alls.RemoveByValue(request))
                        {
                            found = true;
                        }
                        else if (parent.NonAlls.TryGetValue(secId, out var set) && set.Remove(transId))
                        {
                            if (set.Count == 0)
                            {
                                parent.NonAlls.Remove(secId);
                            }

                            found = true;
                        }
                        else
                        {
                            if (parent.Child.TryGetValue(secId, out var child))
                            {
                                if (child.Subscribers.Remove(transId))
                                {
                                    found = true;

                                    if (child.Subscribers.Count == 0)
                                    {
                                        parent.Child.Remove(secId);
                                    }
                                }
                            }
                        }

                        if (found)
                        {
                            if (parent.Alls.Count == 0 && parent.NonAlls.Count == 0 && parent.Child.Count == 0)
                            {
                                // last unsubscribe is not initial subscription
                                if (parent.Origin.TransactionId != originId)
                                {
                                    mdMsg = mdMsg.TypedClone();
                                    mdMsg.OriginalTransactionId = parent.Origin.TransactionId;

                                    message = mdMsg;
                                }

                                _unsubscribes.Add(mdMsg.TransactionId, parent);

                                break;
                            }
                        }

                        RaiseNewOutMessage(mdMsg.CreateResponse(found ? null : new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(originId))));
                        return(true);
                    }
                }

                break;
            }
            }

            return(base.OnSendInMessage(message));
        }
コード例 #4
0
 public ChildSubscription(ParentSubscription parent, MarketDataMessage origin)
     : base(origin)
 {
     Parent = parent ?? throw new ArgumentNullException(nameof(parent));
 }