View Javadoc

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