KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > jdo > PMPool


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.jdo;
13
14 import com.versant.core.common.Debug;
15 import com.versant.core.metric.BaseMetric;
16 import com.versant.core.metric.Metric;
17 import com.versant.core.metric.HasMetrics;
18 import com.versant.core.logging.LogEventStore;
19
20 import java.util.List JavaDoc;
21
22 import com.versant.core.common.BindingSupportImpl;
23 import com.versant.core.metric.HasMetrics;
24 import com.versant.core.logging.LogEventStore;
25
26 /**
27  * This is a pool for PMs. This pool does not have a max limit. It is
28  * thread safe.
29  */

30 public class PMPool implements HasMetrics {
31
32     private final VersantPMFInternal pmf;
33     private int maxIdle;
34
35     private VersantPersistenceManagerImp idleHead; // next con to be given out
36
private VersantPersistenceManagerImp idleTail; // last con returned
37
private int idleCount;
38     private int allocatedCount;
39     private int returnedCount;
40
41     private LogEventStore pes;
42
43     private BaseMetric metricLocalPMIdle;
44     private BaseMetric metricLocalPMAllocated;
45     private BaseMetric metricLocalPMReturned;
46
47     public PMPool(VersantPMFInternal pmf, int maxIdle, LogEventStore pes) {
48         this.pmf = pmf;
49         this.maxIdle = maxIdle;
50         this.pes = pes;
51     }
52
53     /**
54      * Close all connections and shutdown the pool.
55      */

56     public void shutdown() {
57         for (; ;) {
58             VersantPersistenceManagerImp pm = removeFromIdleHead();
59             if (pm == null) break;
60             try {
61                 pm.destroy();
62             } catch (Exception JavaDoc e) {
63                 // ignore
64
}
65         }
66     }
67
68     public String JavaDoc getStatus() {
69         return "idle " + idleCount + "/" + maxIdle;
70     }
71
72     /**
73      * Allocate a PM from the pool.
74      */

75     public synchronized VersantPersistenceManagerImp getPM() {
76         VersantPersistenceManagerImp pm;
77         for (; ;) {
78             pm = removeFromIdleHead();
79             if (pm == null) {
80                 pm = pmf.createVersantPersistenceManagerImp();
81                 break;
82             }
83             if (!pm.isActualClosed()) {
84                 break;
85             }
86         }
87         pm.setInPool(false);
88         ++allocatedCount;
89         if (pes != null && pes.isFine()) {
90             pes.log(new PmPoolEvent(PmPoolEvent.PM_ALLOC, idleCount, maxIdle));
91         }
92         return pm;
93     }
94
95     /**
96      * Return a PM to the pool. This is called when the PM is closed.
97      *
98      * @see VersantPersistenceManagerImp#close
99      */

100     public void returnPM(VersantPersistenceManagerImp pm) {
101         if (!pm.isActualClosed()) {
102             if (idleCount >= maxIdle) {
103                 pm.destroy();
104             } else {
105                 pm.setInPool(true);
106                 pm.resetForPooling();
107                 addToIdleTail(pm);
108             }
109             ++returnedCount;
110             if (pes != null && pes.isFine()) {
111                 pes.log(new PmPoolEvent(PmPoolEvent.PM_RELEASE,
112                         idleCount, maxIdle));
113             }
114         }
115     }
116
117     /**
118      * Add pm to the tail of the idle list. The con has its idle flag set.
119      */

120     private synchronized void addToIdleTail(VersantPersistenceManagerImp pm) {
121         if (Debug.DEBUG) {
122             if (pm.prev != null || pm.next != null) {
123                 throw BindingSupportImpl.getInstance().internal("pm belongs to a list");
124             }
125         }
126         pm.idle = true;
127         if (idleTail == null) {
128             idleHead = idleTail = pm;
129         } else {
130             pm.next = idleTail;
131             idleTail.prev = pm;
132             idleTail = pm;
133         }
134         ++idleCount;
135
136         if (Debug.DEBUG) checkList(idleTail, idleHead, idleCount);
137     }
138
139     /**
140      * Check the integrity of the double linked with head and tail.
141      */

142     private void checkList(VersantPersistenceManagerImp tail,
143             VersantPersistenceManagerImp head, int size) {
144         if (tail == null) {
145             testTrue(head == null);
146             return;
147         }
148         if (head == null) {
149             testTrue(tail == null);
150             return;
151         }
152         checkList(tail, size);
153         checkList(head, size);
154         testTrue(tail.prev == null);
155         testTrue(head.next == null);
156     }
157
158     /**
159      * Check the integrity of the double linked list containing pm.
160      */

161     private void checkList(VersantPersistenceManagerImp pm, int size) {
162         if (pm == null) return;
163         int c = -1;
164         // check links to tail
165
for (VersantPersistenceManagerImp i = pm; i != null; i = i.prev) {
166             if (i.prev != null) testTrue(i.prev.next == i);
167             ++c;
168         }
169         // check links to head
170
for (VersantPersistenceManagerImp i = pm; i != null; i = i.next) {
171             if (i.next != null) testTrue(i.next.prev == i);
172             ++c;
173         }
174         if (size >= 0) {
175             testEquals(size, c);
176         }
177     }
178
179     private static void testEquals(int a, int b) {
180         if (a != b) {
181             throw BindingSupportImpl.getInstance().internal(
182                     "assertion failed: expected " + a + " got " + b);
183         }
184     }
185
186     private static void testTrue(boolean t) {
187         if (!t) {
188             throw BindingSupportImpl.getInstance().internal(
189                     "assertion failed: expected true");
190         }
191     }
192
193     /**
194      * Return the pm at the head of the idle list removing it from the list.
195      * If there is no idle pm then null is returned. The pm has its idle
196      * flag cleared.
197      */

198     private synchronized VersantPersistenceManagerImp removeFromIdleHead() {
199         VersantPersistenceManagerImp pm = idleHead;
200         if (pm == null) return null;
201         idleHead = pm.prev;
202         pm.prev = null;
203         if (idleHead == null) {
204             idleTail = null;
205         } else {
206             idleHead.next = null;
207         }
208         --idleCount;
209         pm.idle = false;
210         if (Debug.DEBUG) checkList(idleTail, idleHead, idleCount);
211         return pm;
212     }
213
214     /**
215      * Add our base performance metrics to list. This is only used for the
216      * local PM pool.
217      */

218     public void addMetrics(List JavaDoc list) {
219         String JavaDoc cat = "PM";
220         list.add(metricLocalPMIdle =
221                 new BaseMetric("PMIdle", "PM Idle", cat,
222                         "Number of idle PMs in pool", 0,
223                         Metric.CALC_AVERAGE));
224         list.add(
225                 metricLocalPMAllocated =
226                 new BaseMetric("PMAlloc", "PM Allocated", cat,
227                         "Number of PMs given out by the pool", 3,
228                         Metric.CALC_DELTA_PER_SECOND));
229         list.add(
230                 metricLocalPMReturned =
231                 new BaseMetric("PMReturned", "PM Returned", cat,
232                         "Number of PMs returned to the pool", 3,
233                         Metric.CALC_DELTA_PER_SECOND));
234     }
235
236     /**
237      * Get values for our metrics. This is only called for the local PM pool.
238      */

239     public void sampleMetrics(int[][] buf, int pos) {
240         buf[metricLocalPMIdle.getIndex()][pos] = idleCount;
241         buf[metricLocalPMAllocated.getIndex()][pos] = allocatedCount;
242         buf[metricLocalPMReturned.getIndex()][pos] = returnedCount;
243     }
244
245 }
246
Popular Tags