示例#1
0
                public TransientBuffer(KeySignature <string> sig, DynamicBuffers parent) : base(parent._parent._calculateAndStoreFromInputAndAsyncTermsOptions)
                {
                    Log.Trace("Constructor Starting");
                    this._parent = parent;
                    Log.Trace($"ElementSet: {sig.Longest().ToString()}");

                    Log.Trace("Creating _buffer");
                    _buffer = new BufferBlock <IInternalMessage <string> >();

                    Log.Trace("Registering _buffer");
                    RegisterChild(_buffer);
                    // critical section
                    // iterate each individual element of the sig, and get those that are not already present in the COD FetchingIndividualElementsOfTerm1
                    foreach (var element in sig.IndividualElements)
                    {
                        if (!parent._parent._calculateAndStoreFromInputAndAsyncTermsObservableData.FetchingIndividualElementsOfTerm1.ContainsKey(element))
                        {
                            // For each element that is not already being fetched, start the async task to fetch it
                            Log.Trace($"Fetching AsyncWebGet for {element} and storing the task in FetchingIndividualElementsOfTerm1 indexed by {element}");
                            // call the async function that fetches the information for each individual element in the elementSet
                            // record the individual element and it's corresponding task in the FetchingIndividualElementsOfTerm1
                            parent._parent._calculateAndStoreFromInputAndAsyncTermsObservableData.FetchingIndividualElementsOfTerm1[element] = parent._parent._webGet.AsyncWebGet <double>(element);
                        }
                    }
                    // Record into FetchingElementSetsOfTerm1 the sig.Longest as key, and for the data,
                    // create a COD whose keys are the keys of sig.IndividualElements in the FetchingElementSetsOfTerm1
                    Log.Trace("Creating new concurrent dictionary");
                    var x = new ConcurrentObservableDictionary <string, byte>();

                    foreach (var element in sig.IndividualElements)
                    {
                        Log.Trace($"Creating an entry for {element}");
                        x[element] = default;
                    }
                    Log.Trace($"Creating an entry for FetchingElementSetsOfTerm1. Key is {sig.Longest()} data is x");
                    parent._parent._calculateAndStoreFromInputAndAsyncTermsObservableData.FetchingElementSetsOfTerm1[sig.Longest()] = x;
                    // If the asyncFetchCheckTimer is not enabled, enable it now.
                    if (!parent._parent.asyncFetchCheckTimer.Enabled)
                    {
                        parent._parent.asyncFetchCheckTimer.Enabled = true;
                    }

                    Log.Trace("Constructor Finished");
                }
示例#2
0
        // Constructor
        public CalculateAndStoreFromInputAndAsyncTerms(CalculateAndStoreFromInputAndAsyncTermsObservableData calculateAndStoreFromInputAndAsyncTermsObservableData, IWebGet webGet, CalculateAndStoreFromInputAndAsyncTermsOptions calculateAndStoreFromInputAndAsyncTermsOptions) : base(calculateAndStoreFromInputAndAsyncTermsOptions)
        {
            Log.Trace("Constructor starting");

            _calculateAndStoreFromInputAndAsyncTermsObservableData = calculateAndStoreFromInputAndAsyncTermsObservableData;
            _webGet = webGet;
            _calculateAndStoreFromInputAndAsyncTermsOptions = calculateAndStoreFromInputAndAsyncTermsOptions;
            // Create a place to store the TransientBuffers that buffer messages while waiting For all elements that make up the ElementSets Of Term1 to finish fetching
            _transientBuffersForElementSetsOfTerm1 = new ConcurrentDictionary <string, Dataflow <IInternalMessage <string>, IInternalMessage <string> > >();

            // foreach IInputMessage<TKeyTerm1,TValueTerm1>, create an internal message that adds the hashset for the terms1  and the bool used by the routing predicate
            Log.Trace("Creating _bAccepter");
            _bAccepter = new TransformBlock <IInputMessage <string, double>, IInternalMessage <string> >(_input => { Log.Trace("Accepter received IInputMessage");
                                                                                                                     // ToDo also check on the async tasks check when an upstream completion occurs
                                                                                                                     // ToDo add exception handling to ensure the tasks, as well as the async method's resources, are released if any blocks in the dataflow fault

                                                                                                                     // create a HashSet from the set of keys found in terms1
                                                                                                                     KeySignature <string> sig = new KeySignature <string>(_input.Value.terms1.Keys);

                                                                                                                     // Is the sig.largest in the ElementSetsOfTerm1Ready dictionary? set the output bool accordingly
                                                                                                                     bool isReadyToCalculate = _calculateAndStoreFromInputAndAsyncTermsObservableData.ElementSetsOfTerm1Ready.ContainsKey(sig.Longest());

                                                                                                                     // Pass the message along to the next block, which will be either the _bSolveStore, or the _bDynamicBuffers
                                                                                                                     return(new InternalMessage <string>((_input.Value.k1, _input.Value.k2, _input.Value.terms1, sig, isReadyToCalculate))); }).ToDataflow();

            // this block accepts messages where isReadyToCalculate is false, and buffers them
            Log.Trace("Creating _bDynamicBuffers");
            _bDynamicBuffers = new DynamicBuffers(this);

            // The terminator block performs both the Solve and the Store operations
            Log.Trace("Creating _bSolveStore");
            _bSolveStore = new ActionBlock <IInternalMessage <string> >(_input => { Log.Trace($"_bSolveStore received InternalMessage having signature {_input.Value.sig.Longest()}");
                                                                                    // solve the equation for the input and all terms
                                                                                    var r1 = 0.0;
                                                                                    foreach (var kvp in _input.Value.terms1)
                                                                                    {
                                                                                        r1 += kvp.Value /
                                                                                              _calculateAndStoreFromInputAndAsyncTermsObservableData.FetchedIndividualElementsOfTerm1[kvp.Key];
                                                                                    }

                                                                                    // Store the results value
                                                                                    calculateAndStoreFromInputAndAsyncTermsObservableData.RecordR(_input.Value.k1,
                                                                                                                                                  _input.Value.k2,
                                                                                                                                                  Convert.ToDecimal(r1)); }).ToDataflow(calculateAndStoreFromInputAndAsyncTermsOptions);


            #region create asyncFetchCheckTimer and connect callback
            // Create a timer that is used to check on the async fetch tasks, the  async fetch tasks check-for-completion loop timer
            // the timer has its interval from the options passed into this constructor, it will restart and the event handler will stop the timer and start the timer each time
            // ToDo add the timer that checks on the health of the async fetch tasks check-for-completion loop every DefaultAsyncFetchTimeout interval, expecting it to provide a heartbeat,
            // The Cleanup method will call this timers Dispose method
            // the event handler's job is to call CheckAsyncTasks which will check for completed fetches and link the child Transient buffers to the _bSolveStore
            Log.Trace("creating and starting the asyncFetchCheckTimer");
            asyncFetchCheckTimer           = new Timer(_calculateAndStoreFromInputAndAsyncTermsOptions.AsyncFetchTimeInterval.TotalMilliseconds);
            asyncFetchCheckTimer.AutoReset = true;
            // set the event handler (callback) for this timer to the function for async fetch tasks check-for-completion loop
            asyncFetchCheckTimer.Elapsed += new ElapsedEventHandler(asyncFetchCheckTimer_Elapsed);
            asyncFetchCheckTimer.Start();
            #endregion create asyncFetchCheckTimer and connect callback
            _bAccepter.Name       = "_bAccepter";
            _bSolveStore.Name     = "_bSolveStore";
            _bDynamicBuffers.Name = "_bDynamicBuffers";

            // Link the data flow
            Log.Trace("Linking dataflow between blocks");
            // Link _bAccepter to _bSolveStore when the InternalMessage.Value has isReadyToCalculate = true
            _bAccepter.LinkTo(_bSolveStore,
                              internalMessage => internalMessage.Value.isReadyToCalculate);
            // Link _bAccepter to _bDynamicBuffers when the  InternalMessage.Value has isReadyToCalculate = false
            _bAccepter.LinkTo(_bDynamicBuffers,
                              internalMessage => !internalMessage.Value.isReadyToCalculate);
            // data flow linkage of the dynamically created TransientBuffer children to the _bSolveStore is complex and handled elsewhere

            // Link the completion tasks
            Log.Trace("Linking completion between blocks");
            _bDynamicBuffers.RegisterDependency(_bAccepter);
            _bSolveStore.RegisterDependency(_bAccepter);
            _bSolveStore.RegisterDependency(_bDynamicBuffers);
            // Completion linkage of the dynamically created TransientBuffer children to the _bSolveStore is complex and handled elsewhere

            Log.Trace("Registering Children");
            this.RegisterChild(_bAccepter);
            this.RegisterChild(_bSolveStore);
            this.RegisterChild(_bDynamicBuffers);

            // set the InputBlock for this dataflow graph to be the InputBlock of the _acceptor
            this._headBlock = _bAccepter.InputBlock;
            // ToDo: add an optional constructor parameter that supplies an initial list of elements that can start pre-fetching for each term
            Log.Trace("Constructor Finished");
        }