/// <summary>
 /// IsEqual - Checks all values to be the same
 /// </summary>
 public static bool IsEqual(this PinkoMsgCalculateExpressionResult src, PinkoMsgCalculateExpressionResult dest)
 {
     return src.DataFeedIdentifier.IsEqual(dest.DataFeedIdentifier)
            &&
            src.ExpressionFormulas.IsEqual(dest.ExpressionFormulas)
         ;
 }
        /// <summary>
        /// Copy all value
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dest"></param>
        /// <returns>Destination passed in parameter</returns>
        public static PinkoMsgCalculateExpressionResult CopyTo(this PinkoMsgCalculateExpression src, PinkoMsgCalculateExpressionResult dest)
        {
            src.DataFeedIdentifier.CopyTo(dest.DataFeedIdentifier);
            dest.ExpressionFormulas = src.ExpressionFormulas.DeepClone();
            dest.ResultType = src.ResultType;

            return dest;
        }
        /// <summary>
        /// Process real time data subscription
        /// </summary>
        public IBusMessageOutbound ProcessSubscribe(IBusMessageInbound envelop, PinkoMsgCalculateExpression expression)
        {
            var response = (IBusMessageOutbound)envelop;
            var marketEnv = PinkoMarketEnvManager.GetMarketEnv(expression.DataFeedIdentifier.MaketEnvId);
            var resultMsg = new PinkoMsgCalculateExpressionResult().FromRequest(expression);

            response.Message = resultMsg;
            response.WebRoleId = expression.DataFeedIdentifier.WebRoleId;

            var finalFormExp = expression.GetExpression();

            Trace.TraceInformation("Calculating: {0}", expression.Verbose());

            //
            // Typed expressions supported are double and double[]
            //
            switch (resultMsg.ResultType)
            {
                // Single double result
                case PinkoCalculateExpressionDaoExtensions.ResultDouble:
                    {
                        var complExp = PinkoExpressionEngine.ParseAndCompile<double[]>(finalFormExp);
                        var results = PinkoExpressionEngine.Invoke(marketEnv, complExp);

                        if (null != results)
                            resultMsg.ResultsTupples = expression.ExpressionFormulas.GetTupleResult(results);
                    }
                    break;

                // 2-dim double[][]
                case PinkoCalculateExpressionDaoExtensions.ResultDoubleSeries:
                    {
                        var complExp = PinkoExpressionEngine.ParseAndCompile<double[][]>(finalFormExp);
                        var results = PinkoExpressionEngine.Invoke(marketEnv, complExp);

                        if (null != results)
                            resultMsg.ResultsTupples = expression.ExpressionFormulas.GetTupleResult(results);
                    }
                    break;

                default:
                    {
                        resultMsg.ResultType = PinkoErrorCode.FormulaTypeNotSupported;
                        response.ErrorCode = PinkoErrorCode.FormulaTypeNotSupported;
                        response.ErrorDescription = PinkoMessagesText.FormulaNotSupported;
                        response.ErrorSystem = PinkoMessagesText.FormulaNotSupported;
                    }
                    break;
            }

            return response;
        }
Пример #4
0
        /// <summary>
        /// Get resulting tuple with envelop and expression
        /// </summary>
        public static Tuple<PinkoMsgCalculateExpressionResult, PinkoServiceMessageEnvelop, PinkoMsgCalculateExpression> GetResultTuple()
        {
            var expression = GetPinkoMsgCalculateExpression()[0];
            var resultMsg = new PinkoMsgCalculateExpressionResult().FromRequest(expression);
            var envelop = new PinkoServiceMessageEnvelop() { Message = expression };

            return new Tuple<PinkoMsgCalculateExpressionResult, PinkoServiceMessageEnvelop, PinkoMsgCalculateExpression>(resultMsg, envelop, expression);
        }
Пример #5
0
        /// <summary>
        /// PinkoMsgCalculateExpressionResult list
        /// </summary>
        public static List<PinkoMsgCalculateExpressionResult> GetPinkoMsgCalculateExpressionResult(int amt = 100)
        {
            return
                GetPinkoMsgCalculateExpression(amt)
                    .Select(x =>
                        {
                            var result = new PinkoMsgCalculateExpressionResult().FromRequest(x);
                            result.ResultsTupples = GetResultsTuppleWrapper().ToArray();

                            return result;
                        })
                    .ToList();
        }
        /// <summary>
        /// Process real time data subscription
        /// </summary>
        public IBusMessageOutbound ProcessSubscribe(IBusMessageInbound envelop, PinkoMsgCalculateExpression expression)
        {
            var response = (IBusMessageOutbound)envelop;
            var resultMsg = new PinkoMsgCalculateExpressionResult().FromRequest(expression);

            response.Message = resultMsg;
            response.WebRoleId = expression.DataFeedIdentifier.WebRoleId;

            // Wait for calculation to end before processing standard request.
            // Avoid have to lock while performing parallel calculations.
            //
            // WARNING: Subscriber collection are NOT thread safe
            //
            using (CalculatingMutex.LockDisposible())
            {
                switch (expression.MsgAction)
                {
                    case PinkoMessageAction.ManagerSubscription:
                        {
                            //
                            // Typed expressions supported are double and double[]
                            //
                            switch (resultMsg.ResultType)
                            {
                                // Single double result
                                case PinkoCalculateExpressionDaoExtensions.ResultDouble:
                                    {
                                        SubscribersDouble.UpdateSubscriber(resultMsg, () => PinkoExpressionEngine.ParseAndCompile<double[]>(expression.GetExpression()));
                                    }
                                    break;

                                // 2-dim double[][]
                                case PinkoCalculateExpressionDaoExtensions.ResultDoubleSeries:
                                    {
                                        SubscribersDoubleDouble.UpdateSubscriber(resultMsg, () => PinkoExpressionEngine.ParseAndCompile<double[][]>(expression.GetExpression()));
                                    }
                                    break;

                                // Invalid result type
                                default:
                                    {
                                        resultMsg.ResultType = PinkoErrorCode.FormulaTypeNotSupported;
                                        response.ErrorCode = PinkoErrorCode.FormulaTypeNotSupported;
                                        response.ErrorDescription = PinkoMessagesText.FormulaNotSupported;
                                        response.ErrorSystem = PinkoMessagesText.FormulaNotSupported;
                                    }
                                    break;
                            }
                        }
                        break;

                    //case PinkoMessageAction.ReconnectSubscribe:
                    //    {
                    //        // TODO: Add unsubscribe
                    //    }
                    //    break;

                    default:
                        {
                            resultMsg.ResultType = PinkoErrorCode.ActionNotSupported;
                            response.ErrorCode = PinkoErrorCode.ActionNotSupported;
                            response.ErrorDescription = PinkoMessagesText.ActionNotSupported;
                            response.ErrorSystem = PinkoMessagesText.ActionNotSupported;
                        }
                        break;
                }
            }

            return response;
        }
        /// <summary>
        /// Process real time data subscription
        /// </summary>
        public IBusMessageOutbound ProcessSubscribe(IBusMessageInbound envelop, PinkoMsgCalculateExpression expression)
        {
            var response = (IBusMessageOutbound)envelop;
            var resultMsg = new PinkoMsgCalculateExpressionResult().FromRequest(expression);

            response.Message = resultMsg;
            response.WebRoleId = expression.DataFeedIdentifier.WebRoleId;

            PinkoMsgCalculateExpression updatedExpMsg = null;
            var isNew = false;

            //  - Do check for current existence
            //  - look for Id changes.
            var clientSubscription =
                ClientSubscriptions.ReplaceCondition(expression.DataFeedIdentifier.SubscribtionId,
                                                     // only replace if null, or expressions are not equal.
                                                     x => (isNew = (null == x)) || !x.CalcExpression.IsEqual(expression),
                                                     x =>
                                                     {
                                                         // create new Runtime ids if formula was changed
                                                         if (null == x || x.CalcExpression.IsFormulaChanged(expression))
                                                             foreach (var formula in expression.ExpressionFormulas)
                                                                 formula.RuntimeId = Interlocked.Increment(ref _runtimeIdSequenceStart);

                                                         return new ClientSubscription() {CalcExpression = expression};
                                                     });

            if (clientSubscription.IsNotNull())
                updatedExpMsg = clientSubscription.CalcExpression;

            // Expression was either replaced, or added
            if (updatedExpMsg.IsNotNull())
            {
                // Update Runtime storage
                PinkoStorage.SaveExpression(PinkoStorageCode.SubsribeBucketName, HandlerPartitionId, expression.DataFeedIdentifier.SubscribtionId, expression);

                // Broadcast to Calc engines that a change happened. They need to update their ids.
                expression.MsgAction = PinkoMessageAction.ManagerSubscription;
                var outboundEnvelop = new PinkoServiceMessageEnvelop()
                {
                    WebRoleId = updatedExpMsg.DataFeedIdentifier.WebRoleId,
                    Message = updatedExpMsg,
                    ReplyTo = envelop.ReplyTo, // string.Empty,  //PinkoConfiguration.PinkoMessageBusToWebRoleCalcResultTopic,
                    //                               New Calc Engine                                             Subscription update to specific role
                    QueueName = isNew ? PinkoConfiguration.PinkoMessageBusToCalcEngineQueue : PinkoConfiguration.PinkoMessageBusToWorkerCalcEngineTopic
                };

                // publish
                TopicPublisher.Publish(outboundEnvelop);

                // do not reply.  The Calc engine will repond to client.
                return null;
            }

            //
            // Unsubscribe
            //  -   remove from storage
            //  -   Tell the calc engines to unsubscribe

            // Calc Engine monitor
            //  -   Monitor calc engines heart beat
            //  -   If failed, the re-subscribe the client

            // Monitor siblings
            //  -   If sibling missing, the take over its subscriptions
            //  -   Load from storage and re-subscribe the client formulas

            return response;
        }