1 2 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 ; 21 22 import com.versant.core.common.BindingSupportImpl; 23 import com.versant.core.metric.HasMetrics; 24 import com.versant.core.logging.LogEventStore; 25 26 30 public class PMPool implements HasMetrics { 31 32 private final VersantPMFInternal pmf; 33 private int maxIdle; 34 35 private VersantPersistenceManagerImp idleHead; private VersantPersistenceManagerImp idleTail; 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 56 public void shutdown() { 57 for (; ;) { 58 VersantPersistenceManagerImp pm = removeFromIdleHead(); 59 if (pm == null) break; 60 try { 61 pm.destroy(); 62 } catch (Exception e) { 63 } 65 } 66 } 67 68 public String getStatus() { 69 return "idle " + idleCount + "/" + maxIdle; 70 } 71 72 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 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 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 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 161 private void checkList(VersantPersistenceManagerImp pm, int size) { 162 if (pm == null) return; 163 int c = -1; 164 for (VersantPersistenceManagerImp i = pm; i != null; i = i.prev) { 166 if (i.prev != null) testTrue(i.prev.next == i); 167 ++c; 168 } 169 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 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 218 public void addMetrics(List list) { 219 String 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 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 |