View Javadoc

1   /*
2    * Copyright (c) 2002 Peter Antman, Teknik i Media  <peter.antman@tim.se>
3    *
4    * $Id: XindicePool.java,v 1.1.1.1 2004/05/19 14:10:47 pra Exp $
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version
10   * 
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   */
20  package org.backsource.xindice;
21  import java.util.Iterator;
22  import java.util.HashMap;
23  import org.apache.log4j.Logger;
24  import EDU.oswego.cs.dl.util.concurrent.Slot;
25  /***
26   * A simple Xindice pool.
27   *
28   *<p>This is a pool for a particular base xindice uri, such as  xmldb:xindice:///db or xmldb:xindice://server:4080/db/. It pools XincdiceAdapter instances, which is actully an adapter for a connection to a specifyed Collection. It will only ever hold one connection for each collection. So for example: getting an adapter for the collection /latest, will create one new if it was never created or let the caller wait until the one created gets available.</p>
29   *
30   * @author <a href="mailto:pra@tim.se">Peter Antman</a>
31   * @version $Revision: 1.1.1.1 $
32   */
33  
34  public class XindicePool {
35     private static final Logger log = Logger.getLogger(XindicePool.class);
36     /*** Wait for max 5 minutes */
37     private static long WAIT = 1000*60*5L;
38     private String url;
39     private HashMap cols = new HashMap();
40     /***
41      * Construct a pool for the specifyed base xindice uri.
42      */
43     public XindicePool (String url){
44        this.url = url;
45     }
46  
47     /***
48      * Get an adapter for the given collection name (relative to the base url), create a new one if newer created or wait until it gets available.
49      *<b>Its verry important</b> that a call to this os followed by a call to {@link #leaveAdapter} in a finally when the method ends that uses the returned adapter.</p>
50      */
51     public XindiceAdapter getAdapter(String col) throws XindiceException {
52        log.debug("Getting adapter for " + col);
53        XindiceAdapter ad = null;
54        Slot slot = null;
55        synchronized(cols) {
56           if ( cols.containsKey(col) ) {
57              slot = (Slot)cols.get(col);         
58           } else {
59              ad = createAdapter(col);
60              slot = new Slot();
61              try {
62                 slot.put(ad);            
63              } catch (java.lang.InterruptedException e) {
64                 throw new XindiceException("Could not create pool entry for col " +col,e);
65              } // end of try-catch
66  
67              cols.put(col,slot);
68           } // end of else
69        }
70        // Threads not looking for the same col will not get stuck here,
71        // but threads looking for the same collection will have to wait until
72        // it gets available.
73        try {
74           ad = (XindiceAdapter)slot.poll(WAIT);
75           if ( ad == null)
76              throw new java.lang.InterruptedException("Timed out waiting on adapter for collection: " + col);
77        } catch (java.lang.InterruptedException  e) {
78           throw new XindiceException("Could not get a new adapter", e);
79        } // end of try-catch
80        log.debug("Returning adapter for " + col);
81        return ad;
82     }
83     
84     /***
85      * Leave the adapter back to the pool.
86      */
87     public void leaveAdapter(XindiceAdapter ad) throws XindiceException {
88        log.debug("Leaving adapter " +ad.getCollectionName());
89        Slot slot = null;
90        String col = ad.getCollectionName();
91        synchronized(cols) {
92           slot = (Slot)cols.get( col );
93        }
94        if ( slot == null) {
95           throw new XindiceException("Cant leave back an adapter that was not created by this pool fpr collection " + col);
96        } 
97        try {         
98           if ( !slot.offer(ad, WAIT)) {
99              throw new java.lang.InterruptedException("Timed out trying to put adapter back in pool for collection: " +  ad.getCollectionName());
100          } // end of if ()
101          
102       } catch (java.lang.InterruptedException e) {
103          throw new XindiceException("Could not put adapter back in pool", e);
104       } // end of try-catch
105       log.debug("Left adapter " +ad.getCollectionName());
106    }
107    
108    public void close() throws XindiceException {
109       synchronized(cols) {
110          // FIXE, use entry so we can get the name of the collection!
111          Iterator it = cols.values().iterator();
112          while (it.hasNext()) {
113             Slot slot = (Slot)it.next();
114             try {
115                XindiceAdapter ad = (XindiceAdapter)slot.poll(1000L);
116                ad.closeCollection();
117                if ( ad == null)
118                   throw new java.lang.InterruptedException("Timed out waiting on adapter for collection");
119             } catch (java.lang.InterruptedException  e) {
120                log.error("Could not close adapter "+e,e);
121             }  catch (XindiceException  e) {
122                log.error("Could not close adapter "+e,e);
123             } // end of try-catch
124          } // end of while ()
125          
126       }
127    }
128    private XindiceAdapter createAdapter(String col) throws XindiceException{
129       return new XindiceAdapter(url,col);
130    }
131 }// XindicePool