Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
CachingWrapperFilter.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using System.Collections;
20 using System.Collections.Generic;
21 using Lucene.Net.Support;
22 using IndexReader = Lucene.Net.Index.IndexReader;
23 using OpenBitSetDISI = Lucene.Net.Util.OpenBitSetDISI;
24 using Lucene.Net.Util;
25 
26 namespace Lucene.Net.Search
27 {
28 
32  [Serializable]
34  {
35  protected internal Filter filter;
36 
58  public enum DeletesMode { IGNORE, RECACHE, DYNAMIC }
59 
60  internal FilterCache<DocIdSet> cache;
61 
62  [Serializable]
63  abstract internal class FilterCache<T> where T : class
64  {
65  /*
66  * A transient Filter cache (package private because of test)
67  */
68  // NOTE: not final so that we can dynamically re-init
69  // after de-serialize
70  volatile IDictionary<Object, T> cache;
71 
72  private DeletesMode deletesMode;
73 
74  public FilterCache(DeletesMode deletesMode)
75  {
76  this.deletesMode = deletesMode;
77  }
78 
79  public T Get(IndexReader reader, object coreKey, object delCoreKey)
80  {
81  lock (this)
82  {
83  T value;
84 
85  if (cache == null)
86  {
87  cache = new WeakDictionary<object, T>();
88  }
89 
90  if (deletesMode == DeletesMode.IGNORE)
91  {
92  // key on core
93  value = cache[coreKey];
94  }
95  else if (deletesMode == DeletesMode.RECACHE)
96  {
97  // key on deletes, if any, else core
98  value = cache[delCoreKey];
99  }
100  else
101  {
102 
103  System.Diagnostics.Debug.Assert(deletesMode == DeletesMode.DYNAMIC);
104 
105  // first try for exact match
106  value = cache[delCoreKey];
107 
108  if (value == null)
109  {
110  // now for core match, but dynamically AND NOT
111  // deletions
112  value = cache[coreKey];
113  if (value != null && reader.HasDeletions)
114  {
115  value = MergeDeletes(reader, value);
116  }
117  }
118  }
119  return value;
120  }
121 
122  }
123 
124  protected abstract T MergeDeletes(IndexReader reader, T value);
125 
126  public void Put(object coreKey, object delCoreKey, T value)
127  {
128  lock (this)
129  {
130  if (deletesMode == DeletesMode.IGNORE)
131  {
132  cache[coreKey] = value;
133  }
134  else if (deletesMode == DeletesMode.RECACHE)
135  {
136  cache[delCoreKey] = value;
137  }
138  else
139  {
140  cache[coreKey] = value;
141  cache[delCoreKey] = value;
142  }
143  }
144  }
145  }
146 
158  public CachingWrapperFilter(Filter filter) : this(filter, DeletesMode.IGNORE)
159  {
160  }
161 
170  public CachingWrapperFilter(Filter filter, DeletesMode deletesMode)
171  {
172  this.filter = filter;
173  cache = new AnonymousFilterCache(deletesMode);
174 
175  //cache = new FilterCache(deletesMode)
176  // {
177  // public Object mergeDeletes(final IndexReader r, final Object docIdSet) {
178  // return new FilteredDocIdSet((DocIdSet) docIdSet) {
179  // protected boolean match(int docID) {
180  // return !r.isDeleted(docID);
181  // }
182  // };
183  // }
184  //};
185  }
186 
187  class AnonymousFilterCache : FilterCache<DocIdSet>
188  {
189  class AnonymousFilteredDocIdSet : FilteredDocIdSet
190  {
191  IndexReader r;
192  public AnonymousFilteredDocIdSet(DocIdSet innerSet, IndexReader r) : base(innerSet)
193  {
194  this.r = r;
195  }
196  public override bool Match(int docid)
197  {
198  return !r.IsDeleted(docid);
199  }
200  }
201 
202  public AnonymousFilterCache(DeletesMode deletesMode) : base(deletesMode)
203  { }
204 
205  protected override DocIdSet MergeDeletes(IndexReader reader, DocIdSet docIdSet)
206  {
207  return new AnonymousFilteredDocIdSet(docIdSet, reader);
208  }
209  }
210 
215  protected internal virtual DocIdSet DocIdSetToCache(DocIdSet docIdSet, IndexReader reader)
216  {
217  if (docIdSet == null)
218  {
219  // this is better than returning null, as the nonnull result can be cached
220  return DocIdSet.EMPTY_DOCIDSET;
221  }
222  else if (docIdSet.IsCacheable) {
223  return docIdSet;
224  }
225  else
226  {
227  DocIdSetIterator it = docIdSet.Iterator();
228  // null is allowed to be returned by iterator(),
229  // in this case we wrap with the empty set,
230  // which is cacheable.
231  return (it == null) ? DocIdSet.EMPTY_DOCIDSET : new OpenBitSetDISI(it, reader.MaxDoc);
232  }
233  }
234 
235  // for testing
236  public int hitCount, missCount;
237 
238  public override DocIdSet GetDocIdSet(IndexReader reader)
239  {
240  object coreKey = reader.FieldCacheKey;
241  object delCoreKey = reader.HasDeletions ? reader.DeletesCacheKey : coreKey;
242 
243  DocIdSet docIdSet = cache.Get(reader, coreKey, delCoreKey);
244 
245  if (docIdSet != null)
246  {
247  hitCount++;
248  return docIdSet;
249  }
250  missCount++;
251  // cache miss
252  docIdSet = DocIdSetToCache(filter.GetDocIdSet(reader), reader);
253 
254  if (docIdSet != null)
255  {
256  cache.Put(coreKey, delCoreKey, docIdSet);
257  }
258 
259  return docIdSet;
260  }
261 
262  public override System.String ToString()
263  {
264  return "CachingWrapperFilter(" + filter + ")";
265  }
266 
267  public override bool Equals(System.Object o)
268  {
269  if (!(o is CachingWrapperFilter))
270  return false;
271  return this.filter.Equals(((CachingWrapperFilter) o).filter);
272  }
273 
274  public override int GetHashCode()
275  {
276  return filter.GetHashCode() ^ 0x1117BF25;
277  }
278  }
279 }