public Result <IReadOnlyList <ContentEvictionInfo> > GetEffectiveLastAccessTimes(
            OperationContext context,
            IReadOnlyList <ContentHashWithLastAccessTime> contentHashes)
        {
            Contract.RequiresNotNull(contentHashes);
            Contract.Requires(contentHashes.Count > 0);

            // This is required because the code inside could throw.

            var    effectiveLastAccessTimes = new List <ContentEvictionInfo>();
            double logInverseMachineRisk    = -Math.Log(_configuration.MachineRisk);

            foreach (var contentHash in contentHashes)
            {
                DateTime    lastAccessTime = contentHash.LastAccessTime;
                int         replicaCount   = 1;
                ReplicaRank rank           = ReplicaRank.None;

                var(localInfo, distributedEntry, isDesignatedLocation) = _contentResolver.GetContentInfo(context, contentHash.Hash);

                // Getting a size from content directory information first.
                long size = localInfo.Size;

                if (distributedEntry != null)
                {
                    // Use the latest last access time between LLS and local last access time
                    DateTime distributedLastAccessTime = distributedEntry.LastAccessTimeUtc.ToDateTime();
                    lastAccessTime = distributedLastAccessTime > lastAccessTime ? distributedLastAccessTime : lastAccessTime;

                    rank = GetReplicaRank(contentHash.Hash, distributedEntry, _contentResolver.LocalMachineId, _configuration, _now);
                    if (isDesignatedLocation)
                    {
                        rank = Combine(ReplicaRank.Designated, rank);
                    }

                    replicaCount = distributedEntry.Locations.Count;

                    if (size == 0)
                    {
                        size = distributedEntry.ContentSize;
                    }
                }

                var localAge     = _now - contentHash.LastAccessTime;
                var age          = _now - lastAccessTime;
                var effectiveAge = GetEffectiveLastAccessTime(_configuration, age, replicaCount, size, rank, logInverseMachineRisk);

                var info = new ContentEvictionInfo(
                    contentHash.Hash,
                    age: age,
                    localAge: localAge,
                    effectiveAge: effectiveAge,
                    replicaCount: replicaCount,
                    size: size,
                    rank: rank);
                effectiveLastAccessTimes.Add(info);
            }

            return(Result.Success <IReadOnlyList <ContentEvictionInfo> >(effectiveLastAccessTimes));
        }
Ejemplo n.º 2
0
 /// <nodoc />
 public ContentEvictionInfo(
     ContentHash contentHash,
     TimeSpan age,
     TimeSpan localAge,
     TimeSpan effectiveAge,
     int replicaCount,
     long size,
     ReplicaRank rank)
 {
     ContentHash  = contentHash;
     Age          = age;
     LocalAge     = localAge;
     EffectiveAge = effectiveAge;
     ReplicaCount = replicaCount;
     Size         = size;
     Rank         = rank;
 }
        public static TimeSpan GetEffectiveLastAccessTime(LocalLocationStoreConfiguration configuration, TimeSpan age, int replicaCount, long size, ReplicaRank rank, double logInverseMachineRisk)
        {
            if (configuration.UseTieredDistributedEviction)
            {
                if (rank == ReplicaRank.Protected)
                {
                    // Protected replicas should be evicted only as a last resort.
                    return(TimeSpan.Zero);
                }

                var ageBucketIndex = FindAgeBucketIndex(configuration, age);
                if (rank != ReplicaRank.None)
                {
                    ageBucketIndex = Math.Max(0, ageBucketIndex - configuration.ImportantReplicaBucketOffset);
                }

                return(configuration.AgeBuckets[ageBucketIndex]);
            }
            else
            {
                // Incorporate both replica count and size into an evictability metric.
                // It's better to eliminate big content (more bytes freed per eviction) and it's better to eliminate content with more replicas (less chance
                // of all replicas being inaccessible).
                // A simple model with exponential decay of likelihood-to-use and a fixed probability of each replica being inaccessible shows that the metric
                //   evictability = age + (time decay parameter) * (-log(risk of content unavailability) * (number of replicas) + log(size of content))
                // minimizes the increase in the probability of (content wanted && all replicas inaccessible) / per bytes freed.
                // Since this metric is just the age plus a computed quantity, it can be interpreted as an "effective age".
                TimeSpan totalReplicaPenalty = TimeSpan.FromMinutes(configuration.ContentLifetime.TotalMinutes * (Math.Max(1, replicaCount) * logInverseMachineRisk + Math.Log(Math.Max(1, size))));
                return(age + totalReplicaPenalty);
            }
        }
 private static ReplicaRank Combine(ReplicaRank rank1, ReplicaRank rank2)
 {
     return((ReplicaRank)Math.Max((byte)rank1, (byte)rank2));
 }