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
TimeLimitingCollector.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 Lucene.Net.Support;
20 using IndexReader = Lucene.Net.Index.IndexReader;
21 
22 namespace Lucene.Net.Search
23 {
24 
31  {
32  private void InitBlock()
33  {
34  greedy = DEFAULT_GREEDY;
35  }
36 
40  public const int DEFAULT_RESOLUTION = 20;
41 
45  public bool DEFAULT_GREEDY = false;
46 
47  private static uint resolution = DEFAULT_RESOLUTION;
48 
49  private bool greedy;
50 
51  private sealed class TimerThread:ThreadClass
52  {
53 
54  // NOTE: we can avoid explicit synchronization here for several reasons:
55  // * updates to volatile long variables are atomic
56  // * only single thread modifies this value
57  // * use of volatile keyword ensures that it does not reside in
58  // a register, but in main memory (so that changes are visible to
59  // other threads).
60  // * visibility of changes does not need to be instantanous, we can
61  // afford losing a tick or two.
62  //
63  // See section 17 of the Java Language Specification for details.
64  private volatile uint time = 0;
65 
71  internal TimerThread():base("TimeLimitedCollector timer thread")
72  {
73  this.IsBackground = true;
74  }
75 
76  override public void Run()
77  {
78  while (true)
79  {
80  // TODO: Use System.nanoTime() when Lucene moves to Java SE 5.
81  time += Lucene.Net.Search.TimeLimitingCollector.resolution;
82  System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * Lucene.Net.Search.TimeLimitingCollector.resolution));
83 
84  }
85  }
86 
88  public long Milliseconds
89  {
90  get { return time; }
91  }
92  }
93 
95  [Serializable]
96  public class TimeExceededException:System.SystemException
97  {
98  private long timeAllowed;
99  private long timeElapsed;
100  private int lastDocCollected;
101  internal TimeExceededException(long timeAllowed, long timeElapsed, int lastDocCollected):base("Elapsed time: " + timeElapsed + "Exceeded allowed search time: " + timeAllowed + " ms.")
102  {
103  this.timeAllowed = timeAllowed;
104  this.timeElapsed = timeElapsed;
105  this.lastDocCollected = lastDocCollected;
106  }
107 
109  public virtual long TimeAllowed
110  {
111  get { return timeAllowed; }
112  }
113 
115  public virtual long TimeElapsed
116  {
117  get { return timeElapsed; }
118  }
119 
121  public virtual int LastDocCollected
122  {
123  get { return lastDocCollected; }
124  }
125  }
126 
127  // Declare and initialize a single static timer thread to be used by
128  // all TimeLimitedCollector instances. The JVM assures that
129  // this only happens once.
130  private static readonly TimerThread TIMER_THREAD = new TimerThread();
131 
132  private long t0;
133  private long timeout;
134  private Collector collector;
135 
136  private int docBase;
137 
143  public TimeLimitingCollector(Collector collector, long timeAllowed)
144  {
145  InitBlock();
146  this.collector = collector;
147  t0 = TIMER_THREAD.Milliseconds;
148  this.timeout = t0 + timeAllowed;
149  }
150 
165  public static long Resolution
166  {
167  get { return resolution; }
168  set
169  {
170  // 5 milliseconds is about the minimum reasonable time for a Object.wait(long) call.
171  resolution = (uint)System.Math.Max(value, 5);
172  }
173  }
174 
181  public virtual bool IsGreedy
182  {
183  get { return greedy; }
184  set { this.greedy = value; }
185  }
186 
194  public override void Collect(int doc)
195  {
196  long time = TIMER_THREAD.Milliseconds;
197  if (timeout < time)
198  {
199  if (greedy)
200  {
201  //System.out.println(this+" greedy: before failing, collecting doc: "+doc+" "+(time-t0));
202  collector.Collect(doc);
203  }
204  //System.out.println(this+" failing on: "+doc+" "+(time-t0));
205  throw new TimeExceededException(timeout - t0, time - t0, docBase + doc);
206  }
207  //System.out.println(this+" collecting: "+doc+" "+(time-t0));
208  collector.Collect(doc);
209  }
210 
211  public override void SetNextReader(IndexReader reader, int base_Renamed)
212  {
213  collector.SetNextReader(reader, base_Renamed);
214  this.docBase = base_Renamed;
215  }
216 
217  public override void SetScorer(Scorer scorer)
218  {
219  collector.SetScorer(scorer);
220  }
221 
222  public override bool AcceptsDocsOutOfOrder
223  {
224  get { return collector.AcceptsDocsOutOfOrder; }
225  }
226 
227  static TimeLimitingCollector()
228  {
229  {
230  TIMER_THREAD.Start();
231  }
232  }
233  }
234 }