Imports DigitalData.Modules.Base Imports DigitalData.Modules.EDMI.API.Client Imports DigitalData.Modules.Logging Namespace DocumentResultList Public Class Cache Inherits BaseClass Implements ICollection(Of Document) Private Const _DefaultCapacity As Long = 1000 Public Shared ReadOnly Property DefaultCapacity As Long Get Return _DefaultCapacity End Get End Property Friend ReadOnly List As New LinkedList(Of Document) Private ReadOnly Index As New Dictionary(Of String, LinkedListNode(Of Document)) Private ReadOnly Lock As New Object Public Sub New(pLogConfig As LogConfig) Me.New(pLogConfig, _DefaultCapacity) End Sub Public Sub New(pLogConfig As LogConfig, pCapacity As Long) MyBase.New(pLogConfig) If pCapacity < 0 Then Throw New InvalidOperationException("DocumentResultCache capacity must be positive.") End If Logger.Debug("Initializing DocumentResultCache with capacity of [{0}] bytes.", pCapacity) Me.Capacity = pCapacity End Sub Public Event DiscardingOldestItem As EventHandler Public Property Capacity As Long Public Property Count As Integer Implements ICollection(Of Document).Count Public ReadOnly Property Oldest As Document Get Return List.First.Value End Get End Property Public Sub Add(pItem As Document) Implements ICollection(Of Document).Add Logger.Debug("Adding document [{0}].", pItem.Id) SyncLock Lock If Index.ContainsKey(pItem.Id) Then List.Remove(Index(pItem.Id)) Index(pItem.Id) = List.AddLast(pItem) Return End If If Count >= Capacity AndAlso Capacity <> 0 Then RaiseEvent DiscardingOldestItem(Me, New EventArgs()) Remove(Oldest) End If Index.Add(pItem.Id, List.AddLast(pItem)) If pItem.Contents IsNot Nothing Then Count += pItem.Contents?.Length End If End SyncLock End Sub Public Function Contains(pItem As Document) As Boolean Implements ICollection(Of Document).Contains Return Index.ContainsKey(pItem.Id) End Function Public Function Contains(pDocumentId As Long) As Boolean Return Index.ContainsKey(pDocumentId) End Function Public Sub CopyTo(pArray As Document(), pIndex As Integer) Implements ICollection(Of Document).CopyTo SyncLock Lock For Each item As Document In Me pArray(Math.Min(System.Threading.Interlocked.Increment(pIndex), pIndex - 1)) = item Next End SyncLock End Sub Public Sub Clear() Implements ICollection(Of Document).Clear SyncLock Lock List.Clear() Index.Clear() End SyncLock End Sub Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of Document).IsReadOnly Get Return False End Get End Property Public Function Remove(pItem As Document) As Boolean Implements ICollection(Of Document).Remove Logger.Debug("Removing document [{0}].", pItem.Id) SyncLock Lock If Index.ContainsKey(pItem.Id) Then List.Remove(Index(pItem.Id)) Index.Remove(pItem.Id) If pItem.Contents IsNot Nothing Then Count -= pItem.Contents.Length End If Return True End If Return False End SyncLock End Function Private Iterator Function GetEnumerator() As IEnumerator(Of Document) Implements ICollection(Of Document).GetEnumerator Dim node As LinkedListNode(Of Document) = List.First While node IsNot Nothing Yield node.Value node = node.[Next] End While End Function Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return DirectCast(List, IEnumerable).GetEnumerator() End Function End Class End Namespace