1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.server.ldap.handlers;
21
22
23 import java.util.concurrent.TimeUnit;
24
25 import org.apache.directory.server.core.cursor.ClosureMonitor;
26 import org.apache.directory.server.core.cursor.CursorClosedException;
27 import org.apache.directory.shared.ldap.exception.LdapTimeLimitExceededException;
28
29
30 /**
31 * A ClosureMonitor implementation which takes into account a time limit.
32 *
33 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
34 * @version $Rev$, $Date$
35 */
36 public class SearchTimeLimitingMonitor implements ClosureMonitor
37 {
38 private final long startTime = System.currentTimeMillis();
39 private final long millisToLive;
40
41 private boolean closed;
42 private Exception cause;
43
44
45 /**
46 * Creates a new instance of SearchTimeLimitingMonitor.
47 *
48 * @param timeToLive the time before changing state to closed.
49 * @param unit the time units for the timeToLive parameter
50 * @see {@link TimeUnit}
51 */
52 public SearchTimeLimitingMonitor( long timeToLive, TimeUnit unit )
53 {
54 switch ( unit )
55 {
56 case MICROSECONDS:
57 this.millisToLive = timeToLive / 1000;
58 break;
59 case MILLISECONDS:
60 this.millisToLive = timeToLive;
61 break;
62 case SECONDS:
63 this.millisToLive = timeToLive * 1000;
64 break;
65 default:
66 throw new IllegalStateException( "TimeUnit not supported: " + unit );
67 }
68 }
69
70
71 /*
72 * (non-Javadoc)
73 * @see org.apache.directory.server.core.cursor.ClosureMonitor#checkNotClosed()
74 */
75 public void checkNotClosed() throws Exception
76 {
77 if ( System.currentTimeMillis() > startTime + millisToLive )
78 {
79 // state check needed to "try" not to overwrite exception (lack of
80 // synchronization may still allow overwriting but who cares that
81 // much
82 if ( ! closed )
83 {
84 // not going to sync because who cares if it takes a little
85 // longer to stop but we need to set cause before toggling
86 // closed state or else check for closure can throw null cause
87 cause = new LdapTimeLimitExceededException();
88 closed = true;
89 }
90 }
91
92 if ( closed )
93 {
94 throw cause;
95 }
96 }
97
98
99 /*
100 * (non-Javadoc)
101 * @see org.apache.directory.server.core.cursor.ClosureMonitor#close()
102 */
103 public void close()
104 {
105 if ( ! closed )
106 {
107 // not going to sync because who cares if it takes a little longer
108 // to stop but we need to set cause before toggling closed state
109 // or else check for closure can throw null cause
110 cause = new CursorClosedException();
111 closed = true;
112 }
113 }
114
115
116 /*
117 * (non-Javadoc)
118 * @see org.apache.directory.server.core.cursor.ClosureMonitor#close(java.lang.String)
119 */
120 public void close( String cause )
121 {
122 if ( ! closed )
123 {
124 // not going to sync because who cares if it takes a little longer
125 // to stop but we need to set cause before toggling closed state
126 // or else check for closure can throw null cause
127 this.cause = new CursorClosedException( cause );
128 closed = true;
129 }
130 }
131
132
133 /*
134 * (non-Javadoc)
135 * @see org.apache.directory.server.core.cursor.ClosureMonitor#close(java.lang.Exception)
136 */
137 public void close( Exception cause )
138 {
139 if ( ! closed )
140 {
141 // not going to sync because who cares if it takes a little longer
142 // to stop but we need to set cause before toggling closed state
143 // or else check for closure can throw null cause
144 this.cause = cause;
145 closed = true;
146 }
147 }
148
149
150 /*
151 * (non-Javadoc)
152 * @see org.apache.directory.server.core.cursor.ClosureMonitor#getCause()
153 */
154 public Exception getCause()
155 {
156 return cause;
157 }
158
159
160 /*
161 * (non-Javadoc)
162 * @see org.apache.directory.server.core.cursor.ClosureMonitor#isClosed()
163 */
164 public boolean isClosed()
165 {
166 if ( System.currentTimeMillis() > startTime + millisToLive )
167 {
168 // set cause first always
169 cause = new LdapTimeLimitExceededException();
170 closed = true;
171 }
172
173 return closed;
174 }
175 }
176
177