diff --git a/DnsServerCore/Dns/Zones/CacheZone.cs b/DnsServerCore/Dns/Zones/CacheZone.cs
index 0b721196..90ea3c92 100644
--- a/DnsServerCore/Dns/Zones/CacheZone.cs
+++ b/DnsServerCore/Dns/Zones/CacheZone.cs
@@ -17,6 +17,7 @@ along with this program. If not, see .
*/
+using DnsServerCore.Dns.ResourceRecords;
using System;
using System.Collections.Generic;
using TechnitiumLibrary;
@@ -60,6 +61,12 @@ namespace DnsServerCore.Dns.Zones
}
}
+ //update last used on
+ DateTime utcNow = DateTime.UtcNow;
+
+ foreach (DnsResourceRecord record in records)
+ record.GetRecordInfo().LastUsedOn = utcNow;
+
return records;
}
@@ -67,7 +74,7 @@ namespace DnsServerCore.Dns.Zones
#region public
- public void SetRecords(DnsResourceRecordType type, IReadOnlyList records, bool serveStale)
+ public bool SetRecords(DnsResourceRecordType type, IReadOnlyList records, bool serveStale)
{
bool isFailureRecord = (records.Count > 0) && records[0].RDATA is DnsCache.DnsSpecialCacheRecord splRecord && splRecord.IsFailureOrBadCache;
if (isFailureRecord)
@@ -76,12 +83,24 @@ namespace DnsServerCore.Dns.Zones
if (_entries.TryGetValue(type, out IReadOnlyList existingRecords))
{
if ((existingRecords.Count > 0) && !(existingRecords[0].RDATA is DnsCache.DnsSpecialCacheRecord existingSplRecord && existingSplRecord.IsFailureOrBadCache) && !DnsResourceRecord.IsRRSetExpired(existingRecords, serveStale))
- return; //skip to avoid overwriting a useful record with a failure record
+ return false; //skip to avoid overwriting a useful record with a failure record
}
}
+ //set last used date time
+ DateTime utcNow = DateTime.UtcNow;
+
+ foreach (DnsResourceRecord record in records)
+ record.GetRecordInfo().LastUsedOn = utcNow;
+
//set records
- _entries[type] = records;
+ bool added = true;
+
+ _entries.AddOrUpdate(type, records, delegate (DnsResourceRecordType key, IReadOnlyList existingRecords)
+ {
+ added = false;
+ return records;
+ });
if (serveStale && !isFailureRecord)
{
@@ -111,15 +130,40 @@ namespace DnsServerCore.Dns.Zones
break;
}
}
+
+ return added;
}
- public void RemoveExpiredRecords(bool serveStale)
+ public int RemoveExpiredRecords(bool serveStale)
{
+ int removedEntries = 0;
+
foreach (KeyValuePair> entry in _entries)
{
if (DnsResourceRecord.IsRRSetExpired(entry.Value, serveStale))
- _entries.TryRemove(entry.Key, out _); //RR Set is expired; remove entry
+ {
+ if (_entries.TryRemove(entry.Key, out _)) //RR Set is expired; remove entry
+ removedEntries++;
+ }
}
+
+ return removedEntries;
+ }
+
+ public int RemoveLeastUsedRecords(DateTime cutoff)
+ {
+ int removedEntries = 0;
+
+ foreach (KeyValuePair> entry in _entries)
+ {
+ if ((entry.Value.Count == 0) || (entry.Value[0].GetRecordInfo().LastUsedOn < cutoff))
+ {
+ if (_entries.TryRemove(entry.Key, out _)) //RR Set was last used before cutoff; remove entry
+ removedEntries++;
+ }
+ }
+
+ return removedEntries;
}
public IReadOnlyList QueryRecords(DnsResourceRecordType type, bool serveStale, bool skipSpecialCacheRecord)
@@ -200,5 +244,12 @@ namespace DnsServerCore.Dns.Zones
}
#endregion
+
+ #region properties
+
+ public int TotalEntries
+ { get { return _entries.Count; } }
+
+ #endregion
}
}