public Tuple <DuplexCallbackId, IDisposable> RegisterObservableCallbacks(int clientId, Action <object> onNext, Action <Exception> onError, Action onCompleted, Action <int> dispose)
        {
            var serverId = Interlocked.Increment(ref lastObservableId);

            var id = new DuplexCallbackId(clientId, serverId);

            var actions = Tuple.Create(onNext, onError, onCompleted, dispose);

            if (!observableCallbacks.TryAdd(id, actions))
            {
                throw new InvalidOperationException(Errors.ProtocolDuplicateDuplexIdForObservable);
            }

            return(Tuple.Create(
                       id,
                       Disposable.Create(() =>
            {
                lock (actions)
                {
                    int?clientSubscriptionId = null;

                    if (TryGetOrAddSubscriptionOneTime(id, ref clientSubscriptionId))
                    {
                        Contract.Assume(clientSubscriptionId.HasValue);                                         // Disposable.Create ensures that this code only runs once

                        actions.Item4(clientSubscriptionId.Value);
                    }
                }
            })));
        }
示例#2
0
        protected void Subscribe(DuplexCallbackId id)
        {
            Func <int, IDisposable> subscribe;

            if (!obsevableCallbacks.TryGetValue(id.ClientId, out subscribe))
            {
                throw new InvalidOperationException(Errors.ProtocolInvalidDuplexId);
            }

            var subscription = new SingleAssignmentDisposable();

            var subscriptionId = RegisterSubscription(subscription);

            try
            {
                subscription.Disposable = subscribe(id.ServerId);
            }
            catch (Exception ex)
            {
                SendOnError(id, ex);
                return;
            }

            SendSubscribeResponse(id, subscriptionId);
        }
示例#3
0
        protected void MoveNext(DuplexCallbackId id)
        {
            var enumerator = GetEnumerator(id.ClientId);

            object current;
            bool   result;

            try
            {
                if (enumerator != null && enumerator.MoveNext())
                {
                    result  = true;
                    current = enumerator.Current;
                }
                else
                {
                    result  = false;
                    current = null;
                }
            }
            catch (Exception ex)
            {
                SendEnumeratorError(id, ex);
                return;
            }

            SendEnumeratorResponse(id, result, current);
        }
        private Tuple <Action <object>, Action <Exception> > GetEnumeratorCallbacks(DuplexCallbackId id)
        {
            Tuple <Action <object>, Action <Exception> > actions;

            if (!enumeratorCallbacks.TryGetValue(id, out actions))
            {
                throw new InvalidOperationException(Errors.ProtocolInvalidDuplexIdForEnumerator);
            }

            return(actions);
        }
        public DuplexCallbackId RegisterEnumeratorCallback(int clientId, Action <object> callback, Action <Exception> onError)
        {
            var serverId = Interlocked.Increment(ref lastEnumeratorId);

            var id = new DuplexCallbackId(clientId, serverId);

            if (!enumeratorCallbacks.TryAdd(id, Tuple.Create(callback, onError)))
            {
                throw new InvalidOperationException(Errors.ProtocolDuplicateDuplexIdForEnumerator);
            }

            return(id);
        }
示例#6
0
        protected void ResetEnumerator(DuplexCallbackId id)
        {
            var enumerator = GetEnumerator(id.ClientId);

            try
            {
                enumerator.Reset();
            }
            catch (Exception ex)
            {
                SendEnumeratorError(id, ex);
            }
        }
        private static byte[] Serialize(DuplexCallbackId id, object value, QbservableProtocol protocol)
        {
            var idData = BitConverter.GetBytes(id);

            long serializedDataLength;
            var  serializedData = protocol.Serialize(value, out serializedDataLength);

            var data = new byte[idData.Length + serializedDataLength];

            Array.Copy(idData, data, idData.Length);
            Array.Copy(serializedData, 0, data, idData.Length, serializedDataLength);

            return(data);
        }
        private void TryInvokeObservableCallback(
            DuplexCallbackId id,
            Action <Tuple <Action <object>, Action <Exception>, Action, Action <int> > > action)
        {
            Tuple <Action <object>, Action <Exception>, Action, Action <int> > callbacks;

            if (observableCallbacks.TryGetValue(id, out callbacks))
            {
                action(callbacks);
            }

            /* It's acceptable for the callbacks to be missing due to a race condition between the
             * client sending notifications and the server disposing of the subscription, which causes
             * the callbacks to be removed.
             */
        }
        private bool TryGetOrAddSubscriptionOneTime(DuplexCallbackId id, ref int?clientSubscriptionId)
        {
            int?s;

            if (subscriptions.TryGetValue(id, out s))
            {
                subscriptions.Remove(id);

                clientSubscriptionId = s;
                return(true);
            }
            else
            {
                subscriptions.Add(id, clientSubscriptionId);
            }

            return(false);
        }
示例#10
0
        protected void GetEnumerator(DuplexCallbackId id)
        {
            var enumerable = GetEnumerable(id.ClientId);

            IEnumerator enumerator;

            try
            {
                enumerator = enumerable();
            }
            catch (Exception ex)
            {
                SendGetEnumeratorError(id, ex);
                return;
            }

            var enumeratorId = RegisterEnumerator(enumerator);

            SendGetEnumeratorResponse(id, enumeratorId);
        }
        protected void HandleSubscribeResponse(DuplexCallbackId id, int clientSubscriptionId)
        {
            Tuple <Action <object>, Action <Exception>, Action, Action <int> > actions;

            if (!observableCallbacks.TryGetValue(id, out actions))
            {
                throw new InvalidOperationException(Errors.ProtocolInvalidDuplexIdForObservable);
            }

            lock (actions)
            {
                int?inputOnly = clientSubscriptionId;
                if (TryGetOrAddSubscriptionOneTime(id, ref inputOnly))
                {
                    subscriptions.Remove(id);

                    Tuple <Action <object>, Action <Exception>, Action, Action <int> > ignored;
                    observableCallbacks.TryRemove(id, out ignored);

                    actions.Item4(clientSubscriptionId);
                }
            }
        }
示例#12
0
        protected void Invoke(DuplexCallbackId id, object[] arguments)
        {
            Func <object[], object> callback;

            if (!invokeCallbacks.TryGetValue(id.ClientId, out callback))
            {
                throw new InvalidOperationException(Errors.ProtocolInvalidDuplexId);
            }

            object result;

            try
            {
                result = callback(arguments);
            }
            catch (Exception ex)
            {
                SendError(id, ex);
                return;
            }

            SendResponse(id, result);
        }
 protected override void SendEnumeratorResponse(DuplexCallbackId id, bool result, object current)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateEnumeratorResponse(id, result, current, protocol));
 }
 public override void SendOnError(DuplexCallbackId id, Exception error)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateOnError(id, error, protocol));
 }
示例#15
0
 protected abstract void SendEnumeratorResponse(DuplexCallbackId id, bool result, object current);
示例#16
0
 public abstract void SendOnCompleted(DuplexCallbackId id);
示例#17
0
 protected abstract void SendSubscribeResponse(DuplexCallbackId id, int clientSubscriptionId);
示例#18
0
 public abstract void SendOnNext(DuplexCallbackId id, object value);
 protected override void SendGetEnumeratorError(DuplexCallbackId id, Exception error)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateGetEnumeratorError(id, error, protocol));
 }
 protected override void SendGetEnumeratorResponse(DuplexCallbackId id, int clientEnumeratorId)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateGetEnumeratorResponse(id, clientEnumeratorId, protocol));
 }
 public override void SendOnCompleted(DuplexCallbackId id)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateOnCompleted(id, protocol));
 }
 private static IDisposable Subscribe(IClientDuplexQbservableProtocolSink sink, DuplexCallbackId id, object instance, Type dataType)
 {
     return(dataType.UpCast(instance).Subscribe(
                value => sink.SendOnNext(id, value),
                ex => sink.SendOnError(id, ex),
                () => sink.SendOnCompleted(id)));
 }
示例#23
0
 public abstract void SendOnError(DuplexCallbackId id, Exception error);
 protected override void SendResponse(DuplexCallbackId id, object result)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateResponse(id, result, protocol));
 }
示例#25
0
 protected abstract void SendResponse(DuplexCallbackId id, object result);
 protected override void SendError(DuplexCallbackId id, Exception error)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateErrorResponse(id, error, protocol));
 }
示例#27
0
 protected abstract void SendGetEnumeratorResponse(DuplexCallbackId id, int clientEnumeratorId);
 protected override void SendSubscribeResponse(DuplexCallbackId id, int clientSubscriptionId)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateSubscribeResponse(id, clientSubscriptionId, protocol));
 }
示例#29
0
 protected abstract void SendEnumeratorError(DuplexCallbackId id, Exception error);
 public override void SendOnNext(DuplexCallbackId id, object value)
 {
     protocol.SendDuplexMessageAsync(DuplexQbservableMessage.CreateOnNext(id, value, protocol));
 }