1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 }
66
67 cols.put(col,slot);
68 }
69 }
70
71
72
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 }
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 }
101
102 } catch (java.lang.InterruptedException e) {
103 throw new XindiceException("Could not put adapter back in pool", e);
104 }
105 log.debug("Left adapter " +ad.getCollectionName());
106 }
107
108 public void close() throws XindiceException {
109 synchronized(cols) {
110
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 }
124 }
125
126 }
127 }
128 private XindiceAdapter createAdapter(String col) throws XindiceException{
129 return new XindiceAdapter(url,col);
130 }
131 }