001: package org.tigris.scarab.util.word;
002:
003: /* ================================================================
004: * Copyright (c) 2003 CollabNet. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are
008: * met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowlegement: "This product includes
019: * software developed by Collab.Net <http://www.Collab.Net/>."
020: * Alternately, this acknowlegement may appear in the software itself, if
021: * and wherever such third-party acknowlegements normally appear.
022: *
023: * 4. The hosted project names must not be used to endorse or promote
024: * products derived from this software without prior written
025: * permission. For written permission, please contact info@collab.net.
026: *
027: * 5. Products derived from this software may not use the "Tigris" or
028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
029: * prior written permission of Collab.Net.
030: *
031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042: *
043: * ====================================================================
044: *
045: * This software consists of voluntary contributions made by many
046: * individuals on behalf of Collab.Net.
047: */
048:
049: // JDK classes
050: import org.tigris.scarab.om.Issue;
051: import org.tigris.scarab.om.IssueType;
052: import org.tigris.scarab.om.MITList;
053: import org.tigris.scarab.om.Module;
054: import org.tigris.scarab.om.ScarabUser;
055: import org.tigris.scarab.tools.localization.L10NKeySet;
056: import org.tigris.scarab.util.ScarabException;
057:
058: /**
059: * Creates new IssueSearch objects and acts as a regulator on the number
060: * of concurrent searches.
061: *
062: * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
063: * @since 0.16.25
064: * @version $Id: IssueSearchFactory.java 10378 2006-12-10 23:34:12Z dabbous $
065: */
066: public class IssueSearchFactory {
067: public static final IssueSearchFactory INSTANCE = new IssueSearchFactory();
068:
069: private final int maxInstances;
070: private final int maxWait;
071:
072: /**
073: * The number of objects currently in use
074: */
075: private int numActive = 0;
076:
077: IssueSearchFactory() {
078: maxInstances = getMaxInstances();
079: maxWait = getMaxWait();
080: }
081:
082: /**
083: * Maximum number of concurrent searches. Given by the
084: * scarab.concurrent.search.max property. if not given
085: * or value is negative, unlimited concurrent searches are
086: * allowed (will then be limited by db connections). A
087: * value of 0 will disable searching.
088: * Implementation note: this method is package-private to
089: * facilitate testing.
090: */
091: int getMaxInstances() {
092: // TODO: FIXME: Should be avalon componente
093: //int max = Turbine.getConfiguration()
094: // .getInt("scarab.concurrent.search.max", -1);
095: //return max;
096: return 2;
097: }
098:
099: /**
100: * How long to wait (in seconds) for a search object if one is not
101: * immediately available. Given by the
102: * scarab.concurrent.search.wait property. if not given
103: * or value is negative, we block till an IssueSearch can be created.
104: * A value of 0 will fail immediately.
105: * Implementation note: this method is package-private to
106: * facilitate testing.
107: */
108: int getMaxWait() {
109: // TODO: FIXME: Should be avalon component.
110: // int max = Turbine.getConfiguration()
111: // .getInt("scarab.concurrent.search.wait", -1);
112: int max = 20; // if for any reason scarab search gets blocked we now get informed on the screen.
113: // instead of getting a frozen scarab. [HD]
114: max *= 1000;
115: return max;
116: }
117:
118: public IssueSearch getInstance(Issue issue, ScarabUser searcher)
119: throws Exception, MaxConcurrentSearchException {
120: register();
121: IssueSearch search = new IssueSearch(issue, searcher);
122: return search;
123: }
124:
125: public IssueSearch getInstance(Module module, IssueType issueType,
126: ScarabUser searcher) throws Exception,
127: MaxConcurrentSearchException {
128: register();
129: IssueSearch search = new IssueSearch(module, issueType,
130: searcher);
131: return search;
132: }
133:
134: public IssueSearch getInstance(MITList mitList, ScarabUser searcher)
135: throws Exception, MaxConcurrentSearchException {
136: register();
137: IssueSearch search = new IssueSearch(mitList, searcher);
138: return search;
139: }
140:
141: void register() throws ScarabException, InterruptedException {
142: if (maxInstances <= 0) {
143: throw new MaxConcurrentSearchException(
144: L10NKeySet.ExceptionSearchIsNotAllowed);
145: } else {
146: synchronized (this ) {
147: long starttime = System.currentTimeMillis();
148: // check if we can create one
149: while (numActive >= maxInstances) {
150: // we can't create a new instance at this moment
151: try {
152: if (maxWait > 0) {
153: wait(maxWait);
154: } else if (maxWait < 0) {
155: wait(); // no god idea becasue potential for frozen Scarab [HD]
156: } else // maxWait == 0
157: {
158: throw new MaxConcurrentSearchException(
159: L10NKeySet.ExceptionMaxConcurrentSearch,
160: "" + this .getMaxWait());
161: }
162: } catch (InterruptedException e) {
163: notify();
164: throw e; //EXCEPTION
165: }
166: if (maxWait > 0
167: && ((System.currentTimeMillis() - starttime) >= maxWait)) {
168: throw new MaxConcurrentSearchException(
169: L10NKeySet.ExceptionMaxConcurrentSearch,
170: "" + this .getMaxWait());
171: }
172: }
173: numActive++;
174: }
175: }
176: }
177:
178: public void notifyDone() {
179: if (maxInstances > 0) {
180: synchronized (this ) {
181: // normally always true, but false is a possibility
182: if (numActive > 0) {
183: numActive--;
184: }
185: if (maxWait != 0) {
186: this .notifyAll(); // give wait'ers a chance at it
187: }
188: }
189: }
190: }
191: }
|