/// <summary> /// Prepare. This method will be invoked after end of configuration and before the first GetValues call /// </summary> public override void Prepare() { try { if (!initializeWasInvoked) { throw new Exception("PrepareForComputation method in SmartWrapper cannot be invoked before the Initialize method has been invoked"); } Validate(); if (validationErrorMessages.Count > 0) { var errorMessage = ""; foreach (string str in validationErrorMessages) { errorMessage += "Error: " + str + ". "; } throw new Exception(errorMessage); } /*foreach (CacheOutputLink cacheOutputLink in _cacheOutputLinks) { cacheOutputLink.UpdateBuffer(); }*/ // start the link monitor //LinkMonitor.Instance.Start(this.cacheOutputLinks, this.traceFile); // MUST BE DONE AFTER LNKS ADDED prefetchHelper = new PrefetchManager(traceFile, statistics, client, scenarioId, dataOutputLinks, TimeHorizon, enablePrefetching, webServiceManager); //PrefetchMonitor.Instance.Start(this.dataOutputLinks, this.traceFile); //PrefetchMonitor.Instance.setTimeHorizon(this.TimeHorizon); prepareForCompotationWasInvoked = true; } catch (Exception e) { var message = "Exception in LinkableComponent. "; message += "ComponentID: " + ComponentID + "\n"; throw new Exception(message, e); } }
/** * Returns the ValueSet that corresponds to requestTime. */ public IValueSet GetValues(ITime requestedTime, IQuantity quantity, IElementSet elementSet, PrefetchManager prefetchManager, ILink link) { try { // generate the key of the buffer entry we're looking for var key = ValueSetEntry.CreateKey(webServiceManager.FindServiceIdForQuantity(quantity.ID), quantity.ID, elementSet.ID, requestedTime, scenarioId); traceFile.Append("GetValues: " + key); var mapValueSet = client.getMap<string, ValueSetEntry>("valueSet"); var mapElementSet = client.getMap<string, ElementSetEntry>("elementSet"); var queueValueSetRequest = client.getQueue<ValueSetRequestEntry>("valueSetRequest"); // record this request statistics.Add("GetValuesCount", 1); // measure our wait time var waitStopwatch = Stopwatch.StartNew(); // see if the requested values are in the cache var valueSetEntry = mapValueSet.get(key); // if the value set does not exist then request it if (valueSetEntry == null) { traceFile.Append("Requesting Value Set: " + key); // insert the element set if necessary if (elementSetsPut.Contains(elementSet.ID) == false) { elementSetsPut.Add(elementSet.ID); mapElementSet.put(elementSet.ID, new ElementSetEntry(elementSet)); } while (valueSetEntry == null) { // if we're prefetching, we may have already requested this // value set in a previous prefetch that hasn't been fulfilled // yet in which case we do not want to issue the request again. if (prefetchManager.timeIsFetched(link, (TimeStamp)requestedTime) == false) { // insert the request into the queue var insertRequestStopwatch = Stopwatch.StartNew(); // create the request entry var valueSetRequestEntry = new ValueSetRequestEntry(webServiceManager.FindServiceIdForQuantity(quantity.ID), quantity.ID, elementSet.ID, Utils.ITimeToDateTime(requestedTime), scenarioId); // BLOCKING queueValueSetRequest.put(valueSetRequestEntry); statistics.Add("RequestInsertTimeMS", insertRequestStopwatch.ElapsedMilliseconds); traceFile.Append("RequestInsertTime:" + string.Format("{0:0.0}", insertRequestStopwatch.ElapsedMilliseconds) + "ms"); } // PERFORMANCE STUDY: start delay at 100 and double each time // we check and it's not available // poll for the value set var delay = 1000; while (true) { // we know that the value set is not in the cache since // we just checked that above, so wait immediately after // making the request Thread.Sleep(delay); valueSetEntry = mapValueSet.get(key); if (valueSetEntry != null) { break; } //delay *= 2; traceFile.Append(string.Format("Waiting ({0}) For Value Set: ({1})", delay, key)); if (delay > 20000) { statistics.Add("RequestRetry", 1); break; } } } } statistics.Add("CacheWaitTimeMS", waitStopwatch.ElapsedMilliseconds); traceFile.Append("WaitTime:" + string.Format("{0:0.0}", waitStopwatch.ElapsedMilliseconds) + "ms"); return new ScalarSet(valueSetEntry.Values()); } catch (Exception e) { traceFile.Exception(e); return null; } }
/// <summary> /// Retrieves a value from the buffer that applies to the time passes as argument. /// During this process the buffer will do temporal operations, /// such as extrapolations, interpolations, or aggregation /// </summary> /// <param name="time">The time for which the values should apply</param> /// <returns>The values</returns> public virtual IValueSet GetValue(ITime time, PrefetchManager prefetchHelper) { // retrieve the values from the cache var values = cacheManager.GetValues(time, link.SourceQuantity, link.SourceElementSet, prefetchHelper, link); // mark this value as already fetched prefetchHelper.addFetchedTime(link, (TimeStamp)time); // perform any new prefetching based on this request prefetchHelper.Update(link); if (_linearDataOperation != null) { values = _linearDataOperation.PerformDataOperation(values); } return ConvertUnit(values); }