Beispiel #1
0
        private ContentLocationEntry GetContentLocationEntry(ShortHash hash)
        {
            if (_map.TryGetValue(hash, out var entry))
            {
                return(ContentLocationEntry.Create(entry.Locations, entry.ContentSize, lastAccessTimeUtc: Clock.UtcNow, creationTimeUtc: null));
            }

            return(ContentLocationEntry.Missing);
        }
Beispiel #2
0
        public void TestContentEvictionWithDesignatedLocation()
        {
            var clock   = new MemoryClock();
            var entries = new List <ContentLocationEntry>();

            entries.Add(
                ContentLocationEntry.Create(
                    locations: CreateWithLocationCount(100),
                    contentSize: 42,
                    lastAccessTimeUtc: clock.UtcNow - TimeSpan.FromHours(2),
                    creationTimeUtc: null));

            entries.Add(
                ContentLocationEntry.Create(
                    locations: CreateWithLocationCount(100),
                    contentSize: 42,
                    lastAccessTimeUtc: clock.UtcNow - TimeSpan.FromHours(2),
                    creationTimeUtc: null));

            entries.Add(
                ContentLocationEntry.Create(
                    locations: CreateWithLocationCount(100),
                    contentSize: 42,
                    lastAccessTimeUtc: clock.UtcNow - TimeSpan.FromHours(2),
                    creationTimeUtc: null));

            var hashes = new[] { ContentHash.Random(), ContentHash.Random(), ContentHash.Random() };

            var mock = new EffectiveLastAccessTimeProviderMock(
                localMachineId: new MachineId(1024),
                isDesignatedLocation: hash => hash == hashes[0]); // The first hash will be designated, and thus important

            mock.Map = new Dictionary <ContentHash, ContentLocationEntry>()
            {
                [hashes[0]] = entries[0],
                [hashes[1]] = entries[1],
                [hashes[2]] = entries[2],
            };

            var provider = new EffectiveLastAccessTimeProvider(Configuration, clock, mock);

            var context = new OperationContext(new Context(Logger));

            // A given machine id index is higher then the max number of locations used in this test.
            // This will prevent the provider to consider non-important locations randomly important
            var input = hashes.Select(hash => new ContentHashWithLastAccessTime(hash, mock.Map[hash].LastAccessTimeUtc.ToDateTime())).ToList();

            var result = provider.GetEffectiveLastAccessTimes(context, input).ShouldBeSuccess();

            var output = result.Value.ToList();

            output.Sort(ContentEvictionInfo.AgeBucketingPrecedenceComparer.Instance);

            // We know that the first hash should be the last one, because this is only important hash in the list.
            output[output.Count - 1].ContentHash.Should().Be(hashes[0]);
        }
Beispiel #3
0
        public void RareContentShouldBeImportant()
        {
            var hash  = ContentHash.Random();
            var clock = new MemoryClock();
            var entry = ContentLocationEntry.Create(
                locations: new ArrayMachineIdSet(new ushort[1]),
                contentSize: 42,
                lastAccessTimeUtc: clock.UtcNow,
                creationTimeUtc: clock.UtcNow);
            bool isImportant = EffectiveLastAccessTimeProvider.IsImportantReplica(hash, entry, new MachineId(1), Configuration.DesiredReplicaRetention);

            isImportant.Should().BeTrue();
        }
Beispiel #4
0
        public void RareContentShouldBeImportant()
        {
            var hash  = ContentHash.Random();
            var clock = new MemoryClock();
            var entry = ContentLocationEntry.Create(
                locations: new ArrayMachineIdSet(new ushort[1]),
                contentSize: 42,
                lastAccessTimeUtc: clock.UtcNow,
                creationTimeUtc: clock.UtcNow);
            var rank = EffectiveLastAccessTimeProvider.GetReplicaRank(hash, entry, new MachineId(1), Configuration, clock.UtcNow);

            rank.Should().Be(ReplicaRank.Important);
        }
Beispiel #5
0
        public void RareContentShouldBeImportantOrProtectedWithThrottling(ushort[] machineIds)
        {
            Configuration.ThrottledEvictionInterval = TimeSpan.FromMinutes(20);

            var hash  = ContentHash.Random();
            var clock = new MemoryClock();

            var entry = ContentLocationEntry.Create(
                locations: new ArrayMachineIdSet(machineIds),
                contentSize: 42,
                lastAccessTimeUtc: clock.UtcNow,
                creationTimeUtc: clock.UtcNow);

            int totalImportantFound = 0;

            foreach (var machineId in machineIds)
            {
                int protectedCount = 0;
                int importantCount = 0;

                for (int i = 0; i < Configuration.DesiredReplicaRetention; i++)
                {
                    var rank = EffectiveLastAccessTimeProvider.GetReplicaRank(hash, entry, new MachineId(machineId), Configuration, clock.UtcNow);
                    clock.UtcNow += Configuration.ThrottledEvictionInterval;

                    switch (rank)
                    {
                    case ReplicaRank.Important:
                        importantCount++;
                        totalImportantFound++;
                        break;

                    case ReplicaRank.Protected:
                        protectedCount++;
                        break;

                    default:
                        XAssert.Fail($"Rank is '{rank}' but should be Important or Protected since content is rare");
                        break;
                    }
                }

                protectedCount.Should().BeInRange(Configuration.DesiredReplicaRetention - 1, Configuration.DesiredReplicaRetention, "At least (DesiredReplicaCount - 1) out of DesiredReplicaCount of the time content should be protected");
                importantCount.Should().BeInRange(0, 1, "At most 1 out of DesiredReplicaCount of the time content should just be important allowing eviction");
            }

            totalImportantFound.Should().Be(1, "Within the time interval (DesiredReplicaCount * ThrottledEvictionInterval), " +
                                            "during exactly one ThrottledEvictionInterval exactly one machine should have content unproteced");
        }
Beispiel #6
0
        public void ContentLocationEntryRoundtrip()
        {
            var model = MetadataServiceSerializer.TypeModel;

            CheckSerializationRoundtrip(model, ContentLocationEntry.Create(
                                            ArrayMachineIdSet.Create(new[] { new MachineId(12), new MachineId(23) }),
                                            12345,
                                            DateTime.UtcNow,
                                            DateTime.UtcNow - TimeSpan.FromDays(1)));

            CheckSerializationRoundtrip(model, ContentLocationEntry.Create(
                                            MachineIdSet.Empty,
                                            46456,
                                            new UnixTime(1)));
        }
Beispiel #7
0
        public void ZeroLocationsShouldNotCauseRuntimeError()
        {
            var hash  = ContentHash.Random();
            var clock = new MemoryClock();
            var entry = ContentLocationEntry.Create(
                locations: new ArrayMachineIdSet(new ushort[0]),
                contentSize: 42,
                lastAccessTimeUtc: clock.UtcNow,
                creationTimeUtc: clock.UtcNow);
            var configuration = new LocalLocationStoreConfiguration()
            {
                ThrottledEvictionInterval = TimeSpan.FromSeconds(1)
            };

            var rank = EffectiveLastAccessTimeProvider.GetReplicaRank(hash, entry, new MachineId(1), configuration, clock.UtcNow);

            rank.Should().Be(ReplicaRank.None);
        }
        /// <nodoc />
        public void StoreResult(OperationContext context, string path, List <string> machines)
        {
            foreach (var machine in machines)
            {
                _knownMachines.GetOrAdd(machine, _ =>
                {
                    var machineId = new MachineId(Interlocked.Increment(ref _currentId));
                    _clusterState.AddMachine(machineId, new MachineLocation(machine));
                    return(machineId);
                });
            }

            var pathHash = ComputePathHash(path);

            var entry = ContentLocationEntry.Create(MachineIdSet.Empty.SetExistence(machines.SelectList(machine => _knownMachines[machine]), true), 0, DateTime.UtcNow);

            _database.Store(context, pathHash, entry);
        }