/// <summary> /// Initialize event type to event mask translation array. /// </summary> static CacheEventFilter() { MASK = new CacheEventMask[4]; MASK[(int)CacheEventType.Inserted] = CacheEventMask.Inserted; MASK[(int)CacheEventType.Updated] = CacheEventMask.Updated | CacheEventMask.UpdatedWithin | CacheEventMask.UpdatedEntered | CacheEventMask.UpdatedLeft; MASK[(int)CacheEventType.Deleted] = CacheEventMask.Deleted; }
/// <summary> /// Construct a <b>CacheEventFilter</b> that evaluates /// <see cref="CacheEventArgs"/> objects based on the specified /// combination of event types. /// </summary> /// <param name="mask"> /// Combination of any of the <see cref="CacheEventMask"/> /// values. /// </param> /// <param name="filter"> /// Optional filter used for evaluating event values. /// </param> /// <param name="maskSynth"> /// Combination of any of the <see cref="CacheEventSyntheticMask"/> /// </param> public CacheEventFilter(CacheEventMask mask, IFilter filter, CacheEventSyntheticMask maskSynth) { if (((int)mask & (int)(CacheEventMask.All | CacheEventMask.Keys | CacheEventMask.UpdatedWithin)) == 0) { throw new ArgumentException("At least one CacheEventMask type must be specified"); } m_mask = mask; m_maskSynth = maskSynth; m_filter = filter; }
/// <summary> /// Return a human-readable description for this /// <b>CacheEventFilter</b>. /// </summary> /// <returns> /// A string description of the <b>CacheEventFilter</b>. /// </returns> public override string ToString() { var sb = new StringBuilder("CacheEventFilter(mask="); CacheEventMask mask = EventMask; if (mask == CacheEventMask.All) { sb.Append("ALL"); } else if (mask == CacheEventMask.Keys) { sb.Append("KEYSET"); } else { if ((mask & CacheEventMask.Inserted) != 0) { sb.Append("INSERTED|"); } if ((mask & CacheEventMask.Updated) != 0) { sb.Append("UPDATED|"); } if ((mask & CacheEventMask.Deleted) != 0) { sb.Append("DELETED|"); } if ((mask & CacheEventMask.UpdatedEntered) != 0) { sb.Append("UPDATED_ENTERED|"); } if ((mask & CacheEventMask.UpdatedLeft) != 0) { sb.Append("UPDATED_LEFT|"); } if ((mask & CacheEventMask.UpdatedWithin) != 0) { sb.Append("UPDATED_WITHIN|"); } sb.Length -= 1; } IFilter filter = Filter; if (filter != null) { sb.Append(", filter=").Append(filter); } sb.Append(", synthetic-mask="); CacheEventSyntheticMask maskSynth = m_maskSynth; if ((maskSynth & CacheEventSyntheticMask.Natural) != 0) { sb.Append("NATURAL|"); } if ((maskSynth & CacheEventSyntheticMask.Synthetic) != 0) { sb.Append("SYNTHETIC|"); } sb.Length -= 1; sb.Append(')'); return(sb.ToString()); }
/// <summary> /// Apply the test to the object. /// </summary> /// <param name="o"> /// An object to which the test is applied. /// </param> /// <returns> /// <b>true</b> if the test passes, <b>false</b> otherwise. /// </returns> public virtual bool Evaluate(object o) { var evt = (CacheEventArgs)o; // check if the event is of a type that the client is // interested in evaluating CacheEventType type = evt.EventType; CacheEventMask mask = EventMask; try { if ((MASK[(int)type] & mask) == 0) { return(false); } } catch (IndexOutOfRangeException) { return(false); } // check for a client-specified event filter IFilter filter = Filter; if (filter == null) { return(true); } CacheEventSyntheticMask maskSynth = m_maskSynth; bool fSynthetic = evt.IsSynthetic; if (((maskSynth & CacheEventSyntheticMask.Synthetic) == 0 && fSynthetic) || ((maskSynth & CacheEventSyntheticMask.Natural) == 0 && !fSynthetic)) { return(false); } // evaluate the filter switch (type) { case CacheEventType.Inserted: return(filter.Evaluate(evt.NewValue)); case CacheEventType.Updated: // note that the old value evaluation is deferred, because // the event itself may be deferring loading the old value, // e.g. if the event is coming from a disk-backed cache bool isNew = filter.Evaluate(evt.NewValue); switch (mask & (CacheEventMask.UpdatedEntered | CacheEventMask.UpdatedLeft | CacheEventMask.Updated | CacheEventMask.UpdatedWithin)) { case CacheEventMask.UpdatedEntered: return(isNew && !filter.Evaluate(evt.OldValue)); case CacheEventMask.UpdatedLeft: return(!isNew && filter.Evaluate(evt.OldValue)); case CacheEventMask.UpdatedEntered | CacheEventMask.UpdatedLeft: return(isNew != filter.Evaluate(evt.OldValue)); case CacheEventMask.UpdatedWithin: return(isNew && filter.Evaluate(evt.OldValue)); case CacheEventMask.UpdatedWithin | CacheEventMask.UpdatedEntered: return(isNew); case CacheEventMask.UpdatedWithin | CacheEventMask.UpdatedLeft: return(filter.Evaluate(evt.OldValue)); default: // all other combinations evaulate to the same as // CacheEventMask.Updated return(isNew || filter.Evaluate(evt.OldValue)); } case CacheEventType.Deleted: return(filter.Evaluate(evt.OldValue)); default: return(false); } }
/// <summary> /// Construct a <b>CacheEventFilter</b> that evaluates /// <see cref="CacheEventArgs"/> objects based on the specified /// combination of event types. /// </summary> /// <param name="mask"> /// Combination of any of the <see cref="CacheEventMask"/> /// values. /// </param> /// <param name="maskSynth"> /// Combination of any of the <see cref="CacheEventSyntheticMask"/> /// </param> public CacheEventFilter(CacheEventMask mask, CacheEventSyntheticMask maskSynth) : this(mask, null, maskSynth) { }
/// <summary> /// Construct a <b>CacheEventFilter</b> that evaluates /// <see cref="CacheEventArgs"/> objects based on the specified /// combination of event types. /// </summary> /// <param name="mask"> /// Combination of any of the <see cref="CacheEventMask"/> /// values. /// </param> /// <param name="filter"> /// Optional filter used for evaluating event values. /// </param> public CacheEventFilter(CacheEventMask mask, IFilter filter) : this(mask, filter, CacheEventSyntheticMask.All) { }
/// <summary> /// Construct a <b>CacheEventFilter</b> that evaluates /// <see cref="CacheEventArgs"/> objects based on the specified /// combination of event types. /// </summary> /// <remarks> /// Using this constructor is equivalent to: /// <code> /// new CacheEventFilter(mask, null, CacheEventSyntheticMask.All); /// </code> /// </remarks> /// <param name="mask"> /// Any combination of <see cref="CacheEventMask.Inserted"/>, /// <see cref="CacheEventMask.Updated"/> and /// <see cref="CacheEventMask.Deleted"/>, /// <see cref="CacheEventMask.UpdatedEntered"/>, /// <see cref="CacheEventMask.UpdatedWithin"/>, /// <see cref="CacheEventMask.UpdatedLeft"/>. /// </param> /// <since>Coherence 3.1</since> public CacheEventFilter(CacheEventMask mask) : this(mask, null, CacheEventSyntheticMask.All) { }