public void MultipleTagInvalidationTest()
        {
            const int MAX_TAG = 10;
            const int MAX_TAG_LIST_LENGTH = 4;

            Random random = new Random();

            for (int iter = 0; iter < 2; iter++)
            {
                TaggedScavengedExpirableCacheStore cacheStore = new TaggedScavengedExpirableCacheStore(new CacheOptions());
                object data = new object();

                for (int i = 0; i < 100000; i++)
                {
                    cacheStore.Set(new CacheItem(Convert.ToString(i), data, 0, TagCacheTestUtil.GetRandomTagsExpirationSpecifier(cacheStore, random, random.Next(1, MAX_TAG_LIST_LENGTH), MAX_TAG)));
                }

                Thread.Sleep(1000);

                for (int j = 0; j < 1000; j++)
                {
                    List<string> tagListToInvalidate = TagCacheTestUtil.GetRandomTagList(random, random.Next(1, MAX_TAG_LIST_LENGTH), MAX_TAG);
                    cacheStore.Invalidate(new List<List<string>> { tagListToInvalidate });
                    _EnsureCacheItemsDontMatch(cacheStore, tagListToInvalidate);
                }
            }
        }
        public void TestMultipleTagInvalidation()
        {
            //10C4 + 10C3 + 10C2 + 10C1 = 385 combinations
            const int MAX_TAG = 10;
            const int MAX_TAG_LIST_LENGTH = 4;

            TaggedScavengedExpirableCacheStore cacheStore = new TaggedScavengedExpirableCacheStore(new CacheOptions());

            Random random = new Random();

            for (int i = 0; i < 500; i++)
            {
                for (int j = 0; j < 1000; j++)
                {
                    cacheStore.Set(new CacheItem(j.ToString(), null, 0, TagCacheTestUtil.GetRandomTagsExpirationSpecifier(cacheStore, random, random.Next(1, MAX_TAG_LIST_LENGTH), MAX_TAG)));
                }

                for (int j = 0; j < 5; j++)
                {
                    List<string> tagListToInvalidate = TagCacheTestUtil.GetRandomTagList(random, random.Next(1, MAX_TAG_LIST_LENGTH), MAX_TAG);
                    cacheStore.Invalidate(new List<List<string>> { tagListToInvalidate });
                    _EnsureCacheItemsDontMatch(cacheStore, tagListToInvalidate);
                }
            }
        }
Example #3
0
 public TagCache(int maxCacheItemCount = 25000, decimal scavengePercentage = 20M)
 {
     _cacheStore = new TaggedScavengedExpirableCacheStore(new CacheOptions
     {
         MaxCacheItemCount = maxCacheItemCount,
         ScavengePercentage = scavengePercentage
     });
 }
        public void SingleTagMultiThreadedBombardTest()
        {
            TaggedScavengedExpirableCacheStore cacheStore = new TaggedScavengedExpirableCacheStore(new CacheOptions());

            Parallel.For(0, 5, (i) => _CacheBombard(cacheStore, new Random(i)));

            // invalidate a few tags in order to ensure purge queue has some value
            Random random = new Random();
            for (int i = 0; i < TagCacheTestUtil.MAX_TAG / 3; i++)
            {
                cacheStore.Invalidate(new List<List<string>> { new List<string> { TagCacheTestUtil.GetRandomTag(random) } });
            }

            _ValidateCacheConsistency(cacheStore);
        }
 public static IExpirationSpecifier[] GetTagExpirationSpecifier(TaggedScavengedExpirableCacheStore cacheStore, List<string> tagList)
 {
     return new IExpirationSpecifier[] { cacheStore.GetTagExpirationSpecifier(tagList) };
 }
 public static IExpirationSpecifier[] GetRandomTagsExpirationSpecifier(TaggedScavengedExpirableCacheStore cacheStore, Random random, int numTags, int maxTag)
 {
     List<string> tagList = GetRandomTagList(random, numTags, maxTag);
     return GetTagExpirationSpecifier(cacheStore, tagList);
 }
        public void TestTagInfoGarbageCollection()
        {
            TaggedScavengedExpirableCacheStore cacheStore = new TaggedScavengedExpirableCacheStore(new CacheOptions());
            Random random = new Random();

            HashSet<string> usedTagSet = new HashSet<string>();

            for (int i = 0; i < 200000; i++)
            {
                string key = TagCacheTestUtil.GetRandomKey(random);
                List<string> tagList = TagCacheTestUtil.GetRandomTagList(random, random.Next(1, 1));

                cacheStore.Set(new CacheItem(key, null, 0, TagCacheTestUtil.GetTagExpirationSpecifier(cacheStore, tagList)));
                usedTagSet.UnionWith(tagList);
            }

            HashSet<string> invalidatedTagSet = new HashSet<string>();

            for (int i = 0; i < TagCacheTestUtil.MAX_TAG * 3 / 4; i++)
            {
                string tag = TagCacheTestUtil.GetRandomTag(random);
                cacheStore.Invalidate(new List<List<string>> { new List<string> { tag } });
                invalidatedTagSet.Add(tag);
            }

            usedTagSet.ExceptWith(invalidatedTagSet);

            List<string> validTagList = new List<string>(usedTagSet);
            _EnsureTags(cacheStore, validTagList);
        }
        private void _ValidateCacheConsistency(TaggedScavengedExpirableCacheStore cacheStore)
        {
            _TouchAllCacheItems(cacheStore);
            _WaitAndGC();

            List<string> tagList = _GetTagsReferredInCacheItems(cacheStore);
            _EnsureTags(cacheStore, tagList);
            _EnsureTagExpirationStateValidity(cacheStore);
        }
 private void _TouchAllCacheItems(TaggedScavengedExpirableCacheStore cacheStore)
 {
     foreach (string key in cacheStore.GetKeys())
     {
         cacheStore.Get(key);
     }
 }
        private List<string> _GetTagsReferredInCacheItems(TaggedScavengedExpirableCacheStore cacheStore)
        {
            HashSet<string> tagSet = new HashSet<string>();

            foreach (string key in cacheStore.GetKeys())
            {
                CacheItem cacheItem = cacheStore.Get(key);
                if (cacheItem != null)
                {
                    IExpirationSpecifier[] expirationSpecifierList = (IExpirationSpecifier[])Array.FindAll(cacheItem.ExpirationSpecifierList, (esp) => esp is TagExpirationSpecifier);
                    foreach (TagExpirationSpecifier expirationSpecifier in expirationSpecifierList)
                    {
                        PropertyInfo propertyInfo = expirationSpecifier.GetType().GetProperty("_TagInfoList", BindingFlags.NonPublic | BindingFlags.Instance);
                        List<TagInfo> tagInfoList = (List<TagInfo>)propertyInfo.GetValue(expirationSpecifier, null);
                        tagInfoList.ForEach(ti => tagSet.Add(ti.Tag));
                    }
                }
            }

            return tagSet.ToList();
        }
        private void _EnsureTags(TaggedScavengedExpirableCacheStore cacheStore, List<string> validTags)
        {
            _TouchAllCacheItems(cacheStore);
            _WaitAndGC();

            TagInfoMap tagInfoMap = (TagInfoMap)cacheStore.GetType().GetProperty("_TagInfoMap", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheStore, null);
            tagInfoMap.GetType().GetMethod("_ScavengeTagMap", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(tagInfoMap, new object[]{});

            ConcurrentDictionary<string, WeakReference> tagInfoByTag = (ConcurrentDictionary<string, WeakReference>)tagInfoMap.GetType().GetProperty("_TagInfoByTag", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(tagInfoMap, null);
            ICollection<string> tagList = tagInfoByTag.Keys;

            int numberOfTagDiscrepencies = 0;
            foreach (string tag in tagList)
            {
                if (!validTags.Contains(tag))
                {
                    numberOfTagDiscrepencies++;
                    _EnsureCacheItemsDontMatch(cacheStore, new List<string> { tag });
                }
            }

            Assert.IsTrue(numberOfTagDiscrepencies == 0, "tag GC failed");
            validTags.ForEach(t => Assert.IsTrue(tagList.Contains(t)));
        }
        private void _EnsureTagExpirationStateValidity(TaggedScavengedExpirableCacheStore cacheStore)
        {
            foreach (string key in cacheStore.GetKeys())
            {
                CacheItem cacheItem = cacheStore.Get(key);
                if (cacheItem != null)
                {
                    IExpirationSpecifier[] expirationSpecifierList = (IExpirationSpecifier[])Array.FindAll(cacheItem.ExpirationSpecifierList, (esp) => esp is TagExpirationSpecifier);
                    foreach (TagExpirationSpecifier expirationSpecifier in expirationSpecifierList)
                    {
                        PropertyInfo tagInfoPropertyInfo = expirationSpecifier.GetType().GetProperty("_TagInfoList", BindingFlags.NonPublic | BindingFlags.Instance);
                        PropertyInfo tagInvalidationPropertyInfo = expirationSpecifier.GetType().GetProperty("_TagInvalidationTokenList", BindingFlags.NonPublic | BindingFlags.Instance);

                        List<TagInfo> tagInfoList = (List<TagInfo>) tagInfoPropertyInfo.GetValue(expirationSpecifier, null);
                        List<object> invalidationTokenList = (List<object>)tagInvalidationPropertyInfo.GetValue(expirationSpecifier, null);

                        for(int i = 0; i < tagInfoList.Count; ++i)
                        {
                            foreach (TagInvalidationInfo invalidationInfo in tagInfoList[i].TagInvalidationInfoList.GetEnumerable(invalidationTokenList[i]))
                            {
                                Assert.Fail("invalidation token is not supposed to be available");
                            }
                        }
                    }
                }
            }
        }
        private void _EnsureCacheItemsDontMatch(TaggedScavengedExpirableCacheStore cacheStore, List<string> tagCombinationList)
        {
            HashSet<string> tagCombination = new HashSet<string>(tagCombinationList);

            foreach (string key in cacheStore.GetKeys())
            {
                CacheItem cacheItem = cacheStore.Get(key);
                if (cacheItem != null)
                {
                    IExpirationSpecifier[] expirationSpecifierList = (IExpirationSpecifier[])Array.FindAll(cacheItem.ExpirationSpecifierList, (esp) => esp is TagExpirationSpecifier);
                    foreach (TagExpirationSpecifier expirationSpecifier in expirationSpecifierList)
                    {
                        PropertyInfo propertyInfo = expirationSpecifier.GetType().GetProperty("_TagInfoList", BindingFlags.NonPublic | BindingFlags.Instance);
                        List<TagInfo> tagInfoList = (List<TagInfo>)propertyInfo.GetValue(expirationSpecifier, null);

                        bool subset = true;
                        foreach(string tag in tagCombinationList)
                        {
                            subset = subset && tagInfoList.Exists(t => t.Tag == tag);
                        }

                        Assert.IsFalse(subset);
                    }
                }
            }
        }
        private void _CacheBombard(TaggedScavengedExpirableCacheStore cacheStore, Random random)
        {
            object data = new object();

            try
            {
                for (int i = 0; i < 100000; i++)
                {
                    double dice = random.NextDouble();

                    if (dice <= 0.3)
                    {
                        cacheStore.Set(new CacheItem(TagCacheTestUtil.GetRandomKey(random), data, 0, TagCacheTestUtil.GetTagExpirationSpecifier(cacheStore, TagCacheTestUtil.GetRandomTagList(random, random.Next(1, 4)))));
                    }
                    else if (dice <= 0.8)
                    {
                        cacheStore.Get(TagCacheTestUtil.GetRandomKey(random));
                    }
                    else if (dice <= 0.9)
                    {
                        cacheStore.Invalidate(new List<List<string>> { new List<string> { TagCacheTestUtil.GetRandomTag(random) } });
                    }
                    else
                    {
                        cacheStore.Remove(TagCacheTestUtil.GetRandomKey(random));
                    }
                }
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.ToString());
            }
        }