示例#1
0
 private void AssertTopicRule(CacheRule rule, string absName)
 {
     int count = CountTopicRuleMatches(rule, absName);
     if (count == 0)
         System.Console.Error.WriteLine("Rule: " + rule.Description);
     Assert.IsTrue(count > 0, "Searching for topic (" + absName + ") in cache rule");
 }
        public void when_deleted_then_execute_cached_then_get_then_check_result()
        {
            var result = cacheProvider.ExecuteCached(new CacheKey(GetType().FullName + "::ComplexReference::Check"),
                                                     () => new ComplexObj(), CacheRule.Delete());

            result = cacheProvider.Get <ComplexObj>(new CacheKey(GetType().FullName + "::ComplexReference::Check"));
            Assert.IsNull(result);

            result = cacheProvider.ExecuteCached(new CacheKey(GetType().FullName + "::ComplexReference::Check"), () => new ComplexObj(), TimeSpan.FromSeconds(4));
            Assert.AreEqual(new ComplexObj().A, result.A);
            Assert.AreEqual(new ComplexObj().B, result.B);

            Thread.Sleep(4000);
            result = cacheProvider.Get <ComplexObj>(new CacheKey(GetType().FullName + "::ComplexReference::Check"));
            Assert.IsNull(result);
        }
示例#3
0
        private T ExecuteCachedInside <T>(CacheKey cacheKey, Func <T> cachedItem, CacheRule cacheRule)
        {
            var cachingProviderTokenSource = new CancellationTokenSource(cancellationTimeoutMs);

            var cacheValue = Get <T>(cacheKey);

            if (cacheRule.ToDelete)
            {
                var svcCount     = services.Count;
                var serviceTasks = new Task[svcCount];
                for (int i = 0; i < svcCount; i++)
                {
                    var i1   = i;
                    var task = Task.Factory.StartNew(() =>
                    {
                        var svcId = services.ElementAt(i1).Key;
                        var svc   = services[svcId];
                        svc.Delete(cacheKey);
                    }, cachingProviderTokenSource.Token);
                    serviceTasks[i1] = task;
                }
                Task.WaitAll(serviceTasks, cachingProviderTokenSource.Token);
                return(default(T));
            }
            if (EqualityComparer <T> .Default.Equals(cacheValue, default(T)) || cacheRule.BypassCache)
            {
                var result       = cachedItem();
                var svcCount     = services.Count;
                var serviceTasks = new Task[svcCount];
                for (int i = 0; i < svcCount; i++)
                {
                    var i1   = i;
                    var task = Task.Factory.StartNew(() =>
                    {
                        var svcId = services.ElementAt(i1).Key;
                        var svc   = services[svcId];
                        svc.Set(cacheKey, new CacheValue(serializer.Serialize(result)), cacheRule);
                    }, cachingProviderTokenSource.Token);
                    serviceTasks[i1] = task;
                }
                Task.WaitAll(serviceTasks, cachingProviderTokenSource.Token);
                return(result);
            }

            return(cacheValue);
        }
示例#4
0
 private int CountTopicRuleMatches(CacheRule rule, string path)
 {
     int found = 0;
     foreach (CacheRule r in rule.AllLeafRules)
     {
         if (r is TopicsCacheRule)
         {
             TopicsCacheRule tcr = (TopicsCacheRule)r;
             foreach (AbsoluteTopicName p in tcr.Topics)
             {
                 if (p.ToString().IndexOf(path) >= 0)
                 {
                     found++;
                 }
             }
         }
     }
     return found;
 }
示例#5
0
		public void Add(CacheRule aRule)
		{
			_Children.Add(aRule);
		}
示例#6
0
 public void Put(string key, object val, CacheRule rule)
 {
     cache[key] = val;
     rules[key] = rule;
 }
        public void Set(CacheKey cacheKey, CacheValue cacheObj, CacheRule cacheRule)
        {
            var db = CacheEndpoint.GetDatabase();

            db.StringSet(cacheKey.ToString(), cacheObj.Value, cacheRule.ExpiresIn);
        }
        public void execute_cached_for_delete_only()
        {
            cacheProvider.ExecuteCached(new CacheKey(GetType().FullName + "::PrimitiveReference::DeleteOnly"), () => Guid.NewGuid(), CacheRule.Delete());
            Assert.True(true);
            var result = cacheProvider.Get <Guid>(new CacheKey(GetType().FullName + "::PrimitiveReference::DeleteOnly"));

            Assert.AreEqual(Guid.Empty.ToString(), result.ToString());
        }
示例#9
0
 public Task <T> ExecuteCachedAsync <T>(CacheKey cacheKey, Func <T> cacheFunc, CacheRule cacheRule)
 {
     return(Task.Factory.StartNew(() => ExecuteCached(cacheKey, cacheFunc, cacheRule)));
 }
示例#10
0
		public void PutCachedTopicsWithProperty(string propertyName, TopicInfoArray val, CacheRule rule)
		{
			string key = KeyForProperty(propertyName);
			Put(key, val, rule);
			rule.SetupInvalidation(this, key);
		}
示例#11
0
		public void PutCachedTopic(AbsoluteTopicName name, CachedTopic val, CacheRule rule)
		{
			string key = KeyForTopicInfo(name);
			Put(key, val, rule);
			rule.SetupInvalidation(this, key);
		}
示例#12
0
		void Put(string key, object val, CacheRule rule)
		{
			Cache.Put(key, val, rule);
		}
示例#13
0
        /// <summary>
        /// Gets the asset from the server.
        /// </summary>
        /// <returns>The asset.</returns>
        /// <param name="assetId">Asset identifier.</param>
        /// <param name="handler">Callback delegate to hand the asset to.</param>
        /// <param name="cacheRule">Bitfield controlling how local storage is to be handled when used as a cache for remote servers.</param>
        public void GetAssetAsync(Guid assetId, AssetHandler handler, CacheRule cacheRule)
        {
            // Ask for null, get null.
            if (assetId == Guid.Empty)
            {
                handler(null);
            }

            // TODO: see if https://github.com/Reactive-Extensions/Rx.NET would do a better job, but they have to finish releasing 4.0 first.

            // It might be beneficial to move the listener processsing to another thread, but then you potentially lose parallism across multiple asset IDs.

            StratusAsset result = null;

            while (true)
            {
                // Hit up the local storage first. If there's no upstream then ignore skipread.
                if (!(cacheRule.HasFlag(CacheRule.SkipRead) && _config.SerialParallelAssetServers.Any()) && (_localStorage?.TryGetAsset(assetId, out result) ?? false))
                {
                    handler(result);
                    return;
                }

                var listeners = new Queue <AssetHandler>();
                listeners.Enqueue(handler);                 // Add myself to the new listeners list first thing, assuming, probably wrongly, that the following test is true.  If wrong, meh: this queue gets dropped like an old potato.
                if (_idsBeingFetched.TryAdd(assetId, listeners))
                {
                    // Got to go try the servers now.
                    foreach (var parallelServers in _config.SerialParallelAssetServers)
                    {
                        if (parallelServers.Count() == 1)                           // Optimization: no need to hit up the parallel stuff if there's only 1.
                        {
                            result = parallelServers.First().RequestAssetSync(assetId);
                        }
                        else
                        {
                            result = parallelServers.AsParallel().Select(server => server.RequestAssetSync(assetId)).FirstOrDefault(a => a != null);
                        }

                        if (result != null)
                        {
                            if (!cacheRule.HasFlag(CacheRule.SkipWrite))
                            {
                                _localStorage?.StoreAsset(result);
                            }
                            break;
                        }
                    }

                    // Now to process the listeners.
                    var exceptions = new ConcurrentQueue <Exception>();

                    lock (listeners) {                     // Prevent new listeners from being added.
                        Parallel.ForEach(listeners, waiting_handler => {
                            if (waiting_handler == null)
                            {
                                LOG.Log(Logging.LogLevel.Warn, () => $"Attempted to process a handler for assetId {assetId} that was null!");
                                return;
                            }

                            try {
                                waiting_handler(result);
                            }
                            catch (Exception e) {
                                exceptions.Enqueue(e);
                            }
                        });

                        _idsBeingFetched.TryRemove(assetId, out var trash);
                    }

                    if (exceptions.Count > 0)
                    {
                        LOG.Log(Logging.LogLevel.Error, () => $"Exceptions ({exceptions.Count}) were thrown by handler(s) listening for asset {assetId}", new AggregateException(exceptions));
                    }

                    return;                     // We're done here.
                }

                // See if we can add ourselves to the listener list.
                if (_idsBeingFetched.TryGetValue(assetId, out listeners))
                {
                    // Skiplock: if the lock cannot be taken, move on to the retry because the list is already being emptied.
                    var lockTaken = false;
                    try {
                        Monitor.TryEnter(listeners, ref lockTaken);
                        if (lockTaken)
                        {
                            listeners.Enqueue(handler);
                            return;
                        }
                    }
                    finally {
                        if (lockTaken)
                        {
                            Monitor.Exit(listeners);
                        }
                    }

                    // lock was skipped, therefore that list is already being cleaned out.
                }

                // It's gone already, so let's try again as the asset should be in local storage or we should query the servers again.
                Thread.Sleep(50);
            }
        }
示例#14
0
 public void Put(string key, object val, CacheRule rule)
 {
     if (rule.IncludesNeverCacheRule)
         return;
     TheCache.Insert(key, val);
     Tracker[key] = rule;
 }
 public void execute_cached_for_delete_only()
 {
     cacheProvider.ExecuteCached(new CacheKey(GetType().FullName + "::PrimitiveReference"), () => "", CacheRule.Delete());
     Assert.True(true);
 }
示例#16
0
		public void AddCacheRule(CacheRule rule)
		{
			_CacheRules.Add(rule);
		}
示例#17
0
 public T ExecuteCached <T>(CacheKey cacheKey, Func <T> cacheFunc, CacheRule cacheRule)
 {
     return(ExecuteCachedInside(cacheKey, cacheFunc, cacheRule));
 }
示例#18
0
		public void PutCachedTopicFormattedBorder(AbsoluteTopicName name, Border border, string val, CacheRule rule)
		{
			string key = KeyForTopicFormattedBorder(name, border);
			Put(key, val, rule);
			rule.SetupInvalidation(this, key);
		}
示例#19
0
		public void PutCachedNamespaceHistory(string ns, IList history, CacheRule rule)
		{
			string key = KeyForNamespaceHistory(ns);
			Put(key, history, rule);
			rule.SetupInvalidation(this, key);
		}
示例#20
0
		public void PutCachedTopicFormattedContent(AbsoluteTopicName name, bool includeDiffs, string val, CacheRule rule)
		{
			string key = KeyForTopicFormattedContent(name, includeDiffs);
			Put(key, val, rule);
			rule.SetupInvalidation(this, key);
		}
示例#21
0
		/// <summary>
		/// Add a cache rule to the cache rule accumulator (or ignore if we aren't accumulating)
		/// </summary>
		/// <param name="aRule"></param>
		void AddCacheRule(CacheRule aRule)
		{
			if (CacheRuleAccumulator != null)
				CacheRuleAccumulator.Add(aRule);
		}
示例#22
0
		public void PutCachedTopicFormattedContent(AbsoluteTopicName name, AbsoluteTopicName withDiffsToThisTopic, string val, CacheRule rule)
		{
			string key = KeyForTopicFormattedContent(name, withDiffsToThisTopic);
			Put(key, val, rule);
			rule.SetupInvalidation(this, key);
		}