Beispiel #1
0
        public void ResetChunkedDoesNothingIfEntryDoesNotExist()
        {
            // given
            var keyOne = new BeaconKey(1, 0);
            var keyTwo = new BeaconKey(666, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(keyOne, 1000L, "a");
            target.AddActionData(keyOne, 1001L, "iii");
            target.AddEventData(keyOne, 1000L, "b");
            target.AddEventData(keyOne, 1001L, "jjj");

            target.PrepareDataForSending(keyOne);

            // do same step we'd do when we send the
            target.GetNextBeaconChunk(keyOne, "prefix", 10, '&');

            // data has been copied, but still add some new event & action data
            target.AddActionData(keyOne, 6666L, "123");
            target.AddEventData(keyOne, 6666L, "987");

            var notifyCount = 0;

            target.RecordAdded += (s, a) => { notifyCount += 1; };

            // and when resetting the previously copied data
            target.ResetChunkedData(keyTwo);

            // then
            Assert.That(target.NumBytesInCache, Is.EqualTo(12L));
            Assert.That(notifyCount, Is.EqualTo(0));
        }
Beispiel #2
0
        public void ExecuteEvictionDoesNotLogIfStrategyIsDisabledAndInfoIsDisabledInLogger()
        {
            // given
            var configuration = MockBeaconCacheConfig(0L, 1000L, 2000L);
            var target        = CreateTimeEvictionStrategyWith(configuration);
            var key           = new BeaconKey(0, 0);

            mockLogger.IsInfoEnabled.Returns(false);

            // when executing the first time
            target.Execute();

            // then
            _ = mockLogger.Received(1).IsInfoEnabled;
            mockLogger.DidNotReceiveWithAnyArgs().Info(string.Empty);
            mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L);

            // and when executing a second time
            target.Execute();

            // then
            _ = mockLogger.Received(2).IsInfoEnabled;
            mockLogger.DidNotReceiveWithAnyArgs().Info(string.Empty);
            mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L);
        }
Beispiel #3
0
        public void RemoveChunkedDataDoesNothingIfCalledWithNonExistingBeaconId()
        {
            // given
            var keyOne = new BeaconKey(1, 0);
            var keyTwo = new BeaconKey(42, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(keyOne, 1000L, "a");
            target.AddActionData(keyOne, 1001L, "iii");
            target.AddActionData(keyTwo, 2000L, "z");
            target.AddEventData(keyOne, 1000L, "b");
            target.AddEventData(keyOne, 1001L, "jjj");

            target.PrepareDataForSending(keyOne);

            // when retrieving the first chunk and removing the wrong beacon chunk
            target.GetNextBeaconChunk(keyOne, "prefix", 10, '&');
            target.RemoveChunkedData(keyTwo);

            // then
            Assert.That(target.GetActionsBeingSent(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") }));
            var expectedEventRecords = new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj") };

            foreach (var record in expectedEventRecords)
            {
                record.MarkForSending();
            }
            Assert.That(target.GetEventsBeingSent(keyOne), Is.EqualTo(expectedEventRecords));
        }
Beispiel #4
0
        public void ResetChunkedRestoresCacheSize()
        {
            // given
            var key = new BeaconKey(1, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(key, 1000L, "a");
            target.AddActionData(key, 1001L, "iii");
            target.AddEventData(key, 1000L, "b");
            target.AddEventData(key, 1001L, "jjj");

            // do same step we'd do when we send the
            target.GetNextBeaconChunk(key, "prefix", 10, '&');

            // data has been copied, but still add some new event & action data
            target.AddActionData(key, 6666L, "123");
            target.AddEventData(key, 6666L, "987");

            // and when resetting the previously copied data
            target.ResetChunkedData(key);

            // then
            Assert.That(target.NumBytesInCache, Is.EqualTo(28L));
        }
Beispiel #5
0
        public void DeleteCacheEntriesDoesNothingIfGivenBeaconIdIsNotInCache()
        {
            // given
            var keyOne   = new BeaconKey(1, 0);
            var keyTwo   = new BeaconKey(42, 0);
            var keyThree = new BeaconKey(666, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(keyOne, 1000L, "a");
            target.AddActionData(keyTwo, 1000L, "z");
            target.AddEventData(keyOne, 1000L, "iii");

            var notifyCount = 0;

            target.RecordAdded += (s, a) => { notifyCount += 1; };

            var cachedSize = target.NumBytesInCache;

            // when
            target.DeleteCacheEntry(keyThree);

            // then
            Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> {
                keyOne, keyTwo
            }));
            Assert.That(target.NumBytesInCache, Is.EqualTo(cachedSize));
            Assert.That(notifyCount, Is.EqualTo(0));
        }
Beispiel #6
0
        public void GetNextBeaconChunkRetrievesNextChunk()
        {
            // given
            var keyOne = new BeaconKey(1, 0);
            var keyTwo = new BeaconKey(42, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(keyOne, 1000L, "a");
            target.AddActionData(keyOne, 1001L, "iii");
            target.AddActionData(keyTwo, 2000L, "z");
            target.AddEventData(keyOne, 1000L, "b");
            target.AddEventData(keyOne, 1001L, "jjj");

            target.PrepareDataForSending(keyOne);

            // when retrieving the first chunk
            var obtained = target.GetNextBeaconChunk(keyOne, "prefix", 10, '&');

            // then
            Assert.That(obtained, Is.EqualTo("prefix&b&jjj"));

            // then
            Assert.That(target.GetActionsBeingSent(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") }));
            var expectedEventRecords = new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj") };

            foreach (var record in expectedEventRecords)
            {
                record.MarkForSending();
            }
            Assert.That(target.GetEventsBeingSent(keyOne), Is.EqualTo(expectedEventRecords));
        }
        public void ExecuteEvictionStopsIfNumBytesInCacheFallsBelowLowerBoundBetweenTwoBeacons()
        {
            // given
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateSpaceEvictionStrategyWith(configuration);

            mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1,                                       //should run method
                                                    configuration.CacheSizeUpperBound,                                           // first iteration
                                                    configuration.CacheSizeUpperBound,                                           // first iteration
                                                    configuration.CacheSizeUpperBound,                                           // first iteration
                                                    (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration
                                                    (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration
                                                    configuration.CacheSizeLowerBound,                                           // stops already (second iteration)
                                                    0L);                                                                         // just for safety

            var keyOne = new BeaconKey(42, 0);
            var keyTwo = new BeaconKey(1, 0);

            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });

            // when executing
            target.Execute();

            // then
            _ = mockBeaconCache.Received(8).NumBytesInCache;
            mockBeaconCache.Received(3).EvictRecordsByNumber(Arg.Any <BeaconKey>(), 1);
        }
Beispiel #8
0
        public void ExecuteEvictionIsStoppedIfThreadGetsInterrupted()
        {
            // given
            var shutdown = false;

            isShutdownFunc = () => shutdown;
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateTimeEvictionStrategyWith(configuration);
            var keyOne        = new BeaconKey(1, 0);
            var keyTwo        = new BeaconKey(42, 0);

            mockTimingProvider.ProvideTimestampInMilliseconds().Returns(1000L, 2099L);

            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });
            mockBeaconCache.EvictRecordsByAge(Arg.Any <BeaconKey>(), Arg.Any <long>())
            .Returns(x =>
            {
                shutdown = true;
                return(2);
            });

            // when
            target.Execute();

            // then verify interactions
            _ = mockBeaconCache.Received(1).BeaconKeys;
            mockBeaconCache.Received(1).EvictRecordsByAge(Arg.Any <BeaconKey>(), 2099L - configuration.MaxRecordAge);
        }
        public void ExecuteEvictionDoesNotLogEvictionResultIfDebugIsDisabled()
        {
            // given
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateSpaceEvictionStrategyWith(configuration);

            mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    0L);
            var keyOne = new BeaconKey(42, 0);
            var keyTwo = new BeaconKey(1, 0);

            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });
            mockBeaconCache.EvictRecordsByNumber(keyTwo, Arg.Any <int>()).Returns(5);
            mockBeaconCache.EvictRecordsByNumber(keyOne, Arg.Any <int>()).Returns(1);

            mockLogger.IsDebugEnabled.Returns(false);

            // when executing the first time
            target.Execute();

            // then
            _ = mockLogger.Received(3).IsDebugEnabled;
            mockLogger.DidNotReceive().Debug(Arg.Any <string>());
        }
        public void ExecuteEvictionRunsUntilTheCacheSizeIsLessThanOrEqualToLowerBound()
        {
            // given
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateSpaceEvictionStrategyWith(configuration);

            mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1,                                       //should run method
                                                    configuration.CacheSizeUpperBound,                                           // first iteration
                                                    configuration.CacheSizeUpperBound,                                           // first iteration
                                                    configuration.CacheSizeUpperBound,                                           // first iteration
                                                    (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration
                                                    (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration
                                                    (configuration.CacheSizeUpperBound + configuration.CacheSizeLowerBound) / 2, // second iteration
                                                    configuration.CacheSizeLowerBound,                                           // stops already
                                                    0L);                                                                         // just for safety

            var keyOne = new BeaconKey(42, 0);
            var keyTwo = new BeaconKey(1, 0);

            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });


            // when executing the first time
            target.Execute();

            // then
            _ = mockBeaconCache.Received(8).NumBytesInCache;
            mockBeaconCache.Received(2).EvictRecordsByNumber(keyTwo, 1);
            mockBeaconCache.Received(2).EvictRecordsByNumber(keyOne, 1);
        }
        public void ExecuteEvictionLogsEvictionResultIfDebugIsEnabled()
        {
            // given
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateSpaceEvictionStrategyWith(configuration);

            mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    0L);
            var keyOne = new BeaconKey(42, 0);
            var keyTwo = new BeaconKey(1, 0);

            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });
            mockBeaconCache.EvictRecordsByNumber(keyTwo, Arg.Any <int>()).Returns(5);
            mockBeaconCache.EvictRecordsByNumber(keyOne, Arg.Any <int>()).Returns(1);

            mockLogger.IsDebugEnabled.Returns(true);

            // when executing the first time
            target.Execute();

            // then
            _ = mockLogger.Received(3).IsDebugEnabled;
            mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 1 records from Beacon with key {keyOne}");
            mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 5 records from Beacon with key {keyTwo}");
        }
        public void ExecuteEvictionCallsCacheMethodForEachBeacon()
        {
            // given
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateSpaceEvictionStrategyWith(configuration);

            mockBeaconCache.NumBytesInCache.Returns(configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    configuration.CacheSizeUpperBound + 1,
                                                    0L);
            var keyOne = new BeaconKey(42, 0);
            var keyTwo = new BeaconKey(1, 0);

            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });

            // when executing the first time
            target.Execute();

            // then
            _ = mockBeaconCache.Received(5).NumBytesInCache;
            mockBeaconCache.Received(1).EvictRecordsByNumber(keyTwo, 1);
            mockBeaconCache.Received(1).EvictRecordsByNumber(keyOne, 1);
        }
Beispiel #13
0
        public virtual string GetNextBeaconChunk(BeaconKey beaconKey, string chunkPrefix, int maxSize, char delimiter)
        {
            var entry = GetCachedEntry(beaconKey);
            if (entry == null)
            {
                // a cache entry for the given beaconKey does not exist
                return null;
            }

            if (entry.NeedsDataCopyBeforeChunking)
            {
                // both entries are null, prepare data for sending
                long numBytes;
                try
                {
                    entry.Lock();
                    numBytes = entry.TotalNumBytes;
                    entry.CopyDataForChunking();

                }
                finally
                {
                    entry.Unlock();
                }
                // assumption: sending will work fine, and everything we copied will be removed quite soon
                Interlocked.Add(ref cacheSizeInBytes, -1L * numBytes);
            }

            // data for chunking is available
            return entry.GetChunk(chunkPrefix, maxSize, delimiter);
        }
Beispiel #14
0
        public int EvictRecordsByNumber(BeaconKey beaconKey, int numRecords)
        {
            var entry = GetCachedEntry(beaconKey);
            if (entry == null)
            {
                // already removed
                return 0;
            }

            int numRecordsRemoved;
            try
            {
                entry.Lock();
                numRecordsRemoved = entry.RemoveOldestRecords(numRecords);
            }
            finally
            {
                entry.Unlock();
            }

            if (logger.IsDebugEnabled)
            {
                var logString = new StringBuilder(GetType().Name)
                    .Append(" EvictRecordsByNumber(sn=").Append(beaconKey.BeaconId.ToInvariantString())
                    .Append(", seq=").Append(beaconKey.BeaconSeqNo.ToInvariantString())
                    .Append(", numRecords=").Append(numRecords.ToInvariantString())
                    .Append(")")
                    .Append(" has evicted ").Append(numRecordsRemoved.ToInvariantString()).Append(" records")
                    .ToString();

                logger.Debug(logString);
            }

            return numRecordsRemoved;
        }
Beispiel #15
0
        public void DeleteCacheEntry(BeaconKey beaconKey)
        {
            if (logger.IsDebugEnabled)
            {
                var logString = new StringBuilder(GetType().Name)
                                .Append(" DeleteCacheEntry(sn=").Append(beaconKey.BeaconId.ToInvariantString())
                                .Append(", seq=").Append(beaconKey.BeaconSeqNo.ToInvariantString())
                                .Append(")")
                                .ToString();

                logger.Debug(logString);
            }
            BeaconCacheEntry entry = null;

            try
            {
                globalCacheLock.EnterWriteLock();
                if (beacons.ContainsKey(beaconKey))
                {
                    entry = beacons[beaconKey];
                    beacons.Remove(beaconKey);
                }
            }
            finally
            {
                globalCacheLock.ExitWriteLock();
            }

            if (entry != null)
            {
                Interlocked.Add(ref cacheSizeInBytes, -1L * entry.TotalNumBytes);
            }
        }
Beispiel #16
0
        public void ExecuteEvictionLogsTheNumberOfRecordsRemoved()
        {
            // given
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateTimeEvictionStrategyWith(configuration);
            var keyOne        = new BeaconKey(1, 0);
            var keyTwo        = new BeaconKey(42, 0);

            mockTimingProvider.ProvideTimestampInMilliseconds().Returns(1000L, 2099L);

            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });
            mockBeaconCache.EvictRecordsByAge(keyOne, Arg.Any <long>()).Returns(2);
            mockBeaconCache.EvictRecordsByAge(keyTwo, Arg.Any <long>()).Returns(5);

            mockLogger.IsDebugEnabled.Returns(true);

            // when
            target.Execute();

            // then verify that the logger was invoked
            _ = mockLogger.Received(2).IsDebugEnabled;
            mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 2 records from Beacon with key {keyOne}");
            mockLogger.Received(1).Debug($"{target.GetType().Name} - Removed 5 records from Beacon with key {keyTwo}");
        }
Beispiel #17
0
        public void PrepareDataForSending(BeaconKey beaconKey)
        {
            var entry = GetCachedEntry(beaconKey);

            if (entry == null)
            {
                // a cache entry for the given beaconKey does not exist
                return;
            }


            if (entry.NeedsDataCopyBeforeSending)
            {
                // both entries are null, prepare data for sending
                long numBytes;
                try
                {
                    entry.Lock();
                    numBytes = entry.TotalNumBytes;
                    entry.CopyDataForSending();
                }
                finally
                {
                    entry.Unlock();
                }
                // assumption: sending will work fine, and everything we copied will be removed quite soon
                Interlocked.Add(ref cacheSizeInBytes, -1L * numBytes);
            }
        }
Beispiel #18
0
        public void DeleteCacheEntryRemovesTheGivenBeacon()
        {
            // given
            var keyOne = new BeaconKey(1, 0);
            var keyTwo = new BeaconKey(42, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(keyOne, 1000L, "a");
            target.AddActionData(keyTwo, 1000L, "z");
            target.AddEventData(keyOne, 1000L, "iii");

            // when removing beacon with id 1
            target.DeleteCacheEntry(keyOne);

            // then
            Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> {
                keyTwo
            }));

            // and when removing beacon with id 42
            target.DeleteCacheEntry(keyTwo);

            // then
            Assert.That(target.BeaconKeys, Is.Empty);
        }
Beispiel #19
0
        public void ResetChunkedData(BeaconKey beaconKey)
        {
            var entry = GetCachedEntry(beaconKey);

            if (entry == null)
            {
                // a cache entry for the given beaconKey does not exist
                return;
            }

            long numBytes;

            try
            {
                entry.Lock();
                var oldSize = entry.TotalNumBytes;
                entry.ResetDataMarkedForSending();
                var newSize = entry.TotalNumBytes;
                numBytes = newSize - oldSize;
            }
            finally
            {
                entry.Unlock();
            }

            Interlocked.Add(ref cacheSizeInBytes, numBytes);

            // notify observers
            OnDataAdded();
        }
Beispiel #20
0
        public void GetNextBeaconChunkDoesNotCopyDataForSending()
        {
            // given
            var keyOne = new BeaconKey(1, 0);
            var keyTwo = new BeaconKey(42, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(keyOne, 1000L, "a");
            target.AddActionData(keyOne, 1001L, "iii");
            target.AddActionData(keyTwo, 2000L, "z");
            target.AddEventData(keyOne, 1000L, "b");
            target.AddEventData(keyOne, 1001L, "jjj");

            // when
            var obtained = target.GetNextBeaconChunk(keyOne, "prefix", 0, '&');

            // then
            Assert.That(obtained, Is.Empty);

            Assert.That(target.GetActions(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") }));
            Assert.That(target.GetEvents(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj") }));
            Assert.That(target.GetActionsBeingSent(keyOne), Is.Null);
            Assert.That(target.GetEventsBeingSent(keyOne), Is.Null);
        }
Beispiel #21
0
        /// <summary>
        /// Get cached <see cref="BeaconCacheEntry"/> or insert new one if nothing exists for given <paramref name="beaconKey"/>.
        /// </summary>
        /// <param name="beaconKey">The beacon key to search for.</param>
        /// <returns>The already cached entry or newly created one.</returns>
        private BeaconCacheEntry GetCachedEntryOrInsert(BeaconKey beaconKey)
        {
            // get the appropriate cache entry
            var entry = GetCachedEntry(beaconKey);

            if (entry == null)
            {
                try
                {
                    // does not exist, and needs to be inserted
                    globalCacheLock.EnterWriteLock();
                    if (!beacons.ContainsKey(beaconKey))
                    {
                        // double check since this could have been added in the mean time
                        entry = new BeaconCacheEntry();
                        beacons.Add(beaconKey, entry);
                    }
                    else
                    {
                        entry = beacons[beaconKey];
                    }
                }
                finally
                {
                    globalCacheLock.ExitWriteLock();
                }
            }

            return(entry);
        }
Beispiel #22
0
        public void AddEventDataAddsBeaconIdToCache()
        {
            // given
            var target = new BeaconCache(logger);
            var keyOne = new BeaconKey(1, 0);
            var keyTwo = new BeaconKey(2, 0);

            // when adding beacon with id 1
            target.AddEventData(keyOne, 1000L, "a");

            // then
            Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> {
                keyOne
            }));
            Assert.That(target.GetEvents(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a") }));

            // and when adding beacon with id 2
            target.AddEventData(keyTwo, 1100L, "b");

            // then
            Assert.That(target.BeaconKeys, Is.EqualTo(new HashSet <BeaconKey> {
                keyOne, keyTwo
            }));
            Assert.That(target.GetEvents(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a") }));
            Assert.That(target.GetEvents(keyTwo), Is.EqualTo(new[] { new BeaconCacheRecord(1100L, "b") }));
        }
Beispiel #23
0
        public void AddEventData(BeaconKey beaconKey, long timestamp, string data)
        {
            if (logger.IsDebugEnabled)
            {
                var logString = new StringBuilder(GetType().Name)
                                .Append(" AddEventData(sn=").Append(beaconKey.BeaconId.ToInvariantString())
                                .Append(", seq=").Append(beaconKey.BeaconSeqNo.ToInvariantString())
                                .Append(", timestamp=").Append(timestamp.ToInvariantString())
                                .Append(", data='").Append(data).Append("')").ToString();

                logger.Debug(logString);
            }
            // get a reference to the cache entry
            var entry = GetCachedEntryOrInsert(beaconKey);

            // add event data for that beacon
            var record = new BeaconCacheRecord(timestamp, data);

            try
            {
                entry.Lock();
                entry.AddEventData(record);
            }
            finally
            {
                entry.Unlock();
            }

            // update cache stats
            Interlocked.Add(ref cacheSizeInBytes, record.DataSizeInBytes);

            // handle event listeners
            OnDataAdded();
        }
Beispiel #24
0
        public void ResetChunkedRestoresData()
        {
            // given
            var key = new BeaconKey(1, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(key, 1000L, "a");
            target.AddActionData(key, 1001L, "iii");
            target.AddEventData(key, 1000L, "b");
            target.AddEventData(key, 1001L, "jjj");

            // do same step we'd do when we send the
            target.GetNextBeaconChunk(key, "prefix", 10, '&');

            // data has been copied, but still add some new event & action data
            target.AddActionData(key, 6666L, "123");
            target.AddEventData(key, 6666L, "987");

            // and when resetting the previously copied data
            target.ResetChunkedData(key);

            // then
            Assert.That(target.GetActionsBeingSent(key), Is.Null);
            Assert.That(target.GetEventsBeingSent(key), Is.Null);
            Assert.That(target.GetActions(key), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii"), new BeaconCacheRecord(6666L, "123") }));
            Assert.That(target.GetEvents(key), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "b"), new BeaconCacheRecord(1001L, "jjj"), new BeaconCacheRecord(6666L, "987") }));
        }
Beispiel #25
0
        public void ExecuteEvictionLogsAMessageOnceAndReturnsIfStrategyIsDisabled()
        {
            // given
            var configuration = MockBeaconCacheConfig(0L, 1000L, 2000L);
            var target        = CreateTimeEvictionStrategyWith(configuration);
            var key           = new BeaconKey(0, 0);

            mockLogger.IsInfoEnabled.Returns(true);

            // when executing the first time
            target.Execute();

            // then
            _ = mockLogger.Received(1).IsInfoEnabled;
            mockLogger.ReceivedWithAnyArgs(1).Info(string.Empty);
            mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L);

            // and when executing a second time
            mockLogger.ClearReceivedCalls();
            target.Execute();

            // then
            _ = mockLogger.DidNotReceive().IsInfoEnabled;
            mockLogger.DidNotReceiveWithAnyArgs().Info(string.Empty);
            mockBeaconCache.DidNotReceiveWithAnyArgs().EvictRecordsByAge(key, 0L);
        }
Beispiel #26
0
        public void ResetChunkedRaisesEvent()
        {
            // given
            var key = new BeaconKey(1, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(key, 1000L, "a");
            target.AddActionData(key, 1001L, "iii");
            target.AddEventData(key, 1000L, "b");
            target.AddEventData(key, 1001L, "jjj");

            // do same step we'd do when we send the
            target.GetNextBeaconChunk(key, "prefix", 10, '&');

            // data has been copied, but still add some new event & action data
            target.AddActionData(key, 6666L, "123");
            target.AddEventData(key, 6666L, "987");

            var notifyCount = 0;

            target.RecordAdded += (s, a) => { notifyCount += 1; };

            // and when resetting the previously copied data
            target.ResetChunkedData(key);

            // then
            Assert.That(notifyCount, Is.EqualTo(1));
        }
Beispiel #27
0
        public void ExecuteEvictionCallsEvictionForEachBeaconSeparately()
        {
            // given
            var configuration = MockBeaconCacheConfig(1000L, 1000L, 2000L);
            var target        = CreateTimeEvictionStrategyWith(configuration);
            var keyOne        = new BeaconKey(1, 0);
            var keyTwo        = new BeaconKey(42, 0);

            mockTimingProvider.ProvideTimestampInMilliseconds().Returns(1000L, 2099L);
            mockBeaconCache.BeaconKeys.Returns(new HashSet <BeaconKey> {
                keyOne, keyTwo
            });

            // when
            target.Execute();

            // then verify interactions
            _ = mockBeaconCache.Received(1).BeaconKeys;
            mockBeaconCache.Received(1).EvictRecordsByAge(keyOne, 2099L - configuration.MaxRecordAge);
            mockBeaconCache.Received(1).EvictRecordsByAge(keyTwo, 2099L - configuration.MaxRecordAge);
            mockTimingProvider.Received(3).ProvideTimestampInMilliseconds();

            // also ensure that the last run timestamp was updated
            Assert.That(target.LastRunTimestamp, Is.EqualTo(2099L));
        }
        public void RemoveChunkedDataClearsAlreadyRetrievedChunks()
        {
            // given
            var keyOne = new BeaconKey(1, 0);
            var keyTwo = new BeaconKey(42, 0);

            var target = new BeaconCache(logger);

            target.AddActionData(keyOne, 1000L, "a");
            target.AddActionData(keyOne, 1001L, "iii");
            target.AddActionData(keyTwo, 2000L, "z");
            target.AddEventData(keyOne, 1000L, "b");
            target.AddEventData(keyOne, 1001L, "jjj");

            // when retrieving the first chunk and removing retrieved chunks
            var obtained = target.GetNextBeaconChunk(keyOne, "prefix", 10, '&');

            target.RemoveChunkedData(keyOne);

            // then
            Assert.That(obtained, Is.EqualTo("prefix&b&jjj"));

            Assert.That(target.GetActionsBeingSent(keyOne), Is.EqualTo(new[] { new BeaconCacheRecord(1000L, "a"), new BeaconCacheRecord(1001L, "iii") }));
            Assert.That(target.GetEventsBeingSent(keyOne), Is.Empty);

            // when retrieving the second chunk and removing retrieved chunks
            obtained = target.GetNextBeaconChunk(keyOne, "prefix", 10, '&');
            target.RemoveChunkedData(keyOne);

            // then
            Assert.That(obtained, Is.EqualTo("prefix&a&iii"));

            Assert.That(target.GetActionsBeingSent(keyOne), Is.Empty);
            Assert.That(target.GetEventsBeingSent(keyOne), Is.Empty);
        }
Beispiel #29
0
        public void InstancesWithDifferentBeaconIdHaveDifferentHash()
        {
            // given
            var keyOne = new BeaconKey(37, 18);
            var keyTwo = new BeaconKey(38, 18);

            // when, then
            Assert.That(keyOne.GetHashCode(), Is.Not.EqualTo(keyTwo.GetHashCode()));
        }
Beispiel #30
0
        public void InstancesWithSameValuesHaveSameHash()
        {
            // given
            var keyOne = new BeaconKey(17, 18);
            var keyTwo = new BeaconKey(17, 18);

            // when, then
            Assert.That(keyOne.GetHashCode(), Is.EqualTo(keyTwo.GetHashCode()));
        }