-
Notifications
You must be signed in to change notification settings - Fork 242
/
TimeoutManager.java
153 lines (132 loc) · 3.38 KB
/
TimeoutManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package org.hibernate.search.query;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
import org.apache.lucene.search.Query;
import org.hibernate.QueryTimeoutException;
import org.hibernate.search.SearchException;
/**
* @author Emmanuel Bernard
*/
public class TimeoutManager {
// timeout in nanoseconds
private Long timeout;
private long start;
boolean timedOut = false;
private Query luceneQuery;
private Type type;
private boolean partialResults;
public TimeoutManager() {
}
/** we start counting from this method call (if needed) */
public void start(Query luceneQuery) {
if ( timeout == null ) return;
this.luceneQuery = luceneQuery;
this.start = System.nanoTime();
this.partialResults = false;
}
public Long getTimeoutLeftInMilliseconds() {
return getTimeoutLeft( 1000000 );
}
public Long getTimeoutLeftInSeconds() {
return getTimeoutLeft(1000000000);
}
private Long getTimeoutLeft(long factor) {
if (timeout == null) {
return null;
}
else {
final long currentTime = System.nanoTime();
if ( isTimedOut( currentTime ) ) {
//0 means no limit so we return the lowest possible value
return 1l;
}
long left = timeout - ( currentTime - start);
long result;
if ( left % factor == 0 ) {
result = left / factor;
}
else {
result = (left / factor) + 1;
}
if ( result <= 0 ) {
//0 means no limit so we return the lowest possible value
return 1l;
}
else {
return result;
}
}
}
public boolean isTimedOut() {
if ( timeout == null ) return false;
if ( timedOut ) {
return true;
}
return isTimedOut( System.nanoTime() );
}
private boolean isTimedOut(long currentTime) {
if ( timeout == null ) return false;
if ( timedOut ) {
return true;
}
else {
final long elapsedTime = currentTime - start;
timedOut = elapsedTime > timeout;
if ( this.type != Type.LIMIT ) {
throw new QueryTimeoutException(
"Full-text query took longer than expected (in microsecond): " + TimeUnit.NANOSECONDS.toMicros( elapsedTime ),
( SQLException) null,
luceneQuery.toString()
);
}
return timedOut;
}
}
public void stop() {
this.timeout = null;
this.type = Type.NONE;
this.partialResults = false;
}
public void setTimeout(long timeout, TimeUnit timeUnit) {
this.timeout = timeUnit.toNanos( timeout );
//timeout of 0 means no more timeout
if ( timeout == 0 ) {
stop();
}
}
public void forceTimedOut() {
this.timedOut = Boolean.TRUE;
}
public void raiseExceptionOnTimeout() {
if ( this.type == Type.LIMIT ) {
throw new SearchException("Cannot define both setTimeout and limitFetchingTime on a full-text query. Please report your need to the Hibernate team");
}
this.type = Type.EXCEPTION;
}
public void limitFetchingOnTimeout() {
if ( this.type == Type.EXCEPTION ) {
throw new SearchException("Cannot define both setTimeout and limitFetchingTime on a full-text query. Please report your need to the Hibernate team");
}
this.type = Type.LIMIT;
}
public void reactOnQueryTimeoutExceptionWhileExtracting(QueryTimeoutException e) {
if ( type == Type.LIMIT) {
//we stop where we are return what we have
this.partialResults = true;
}
else {
throw e;
}
}
public boolean hasPartialResults() {
return partialResults;
}
public Type getType() {
return type;
}
public static enum Type {
NONE,
EXCEPTION,
LIMIT
}
}