1 11 package mondrian.util; 12 13 import mondrian.olap.MondrianProperties; 14 import org.apache.log4j.Logger; 15 import java.util.LinkedList ; 16 import java.util.ListIterator ; 17 18 26 public abstract class AbstractMemoryMonitor 27 implements MemoryMonitor, MemoryMonitor.Test { 28 29 32 private static final int MAX_PERCENTAGE = 100; 33 34 37 static class Entry { 38 final Listener listener; 39 long threshold; 40 Entry(final Listener listener, final long threshold) { 41 this.listener = listener; 42 this.threshold = threshold; 43 } 44 public boolean equals(final Object other) { 45 return (other instanceof Entry) && 46 (listener == ((Entry) other).listener); 47 } 48 public int hashCode() { 49 return listener.hashCode(); 50 } 51 } 52 53 58 private final LinkedList <Entry> listeners; 59 60 64 private long lowThreshold; 65 66 69 protected AbstractMemoryMonitor() { 70 listeners = new LinkedList <Entry>(); 71 } 72 73 78 protected abstract Logger getLogger(); 79 80 86 protected long getLowThreshold() { 87 return lowThreshold; 88 } 89 90 98 public int getDefaultThresholdPercentage() { 99 return MondrianProperties.instance().MemoryMonitorThreshold.get(); 100 } 101 102 113 public boolean addListener(final Listener listener) { 114 return addListener(listener, getDefaultThresholdPercentage()); 115 } 116 117 130 public boolean addListener(Listener listener, int percentage) { 131 getLogger().info("addListener enter"); 132 try { 133 138 139 final long newThreshold = convertPercentageToThreshold(percentage); 140 Entry e = new Entry(listener, newThreshold); 141 142 synchronized (listeners) { 143 long prevLowThreshold = generateLowThreshold(); 144 145 final ListIterator <Entry> iter = listeners.listIterator(); 148 while (iter.hasNext()) { 149 Entry ee = iter.next(); 150 if (newThreshold <= ee.threshold) { 151 iter.add(e); 152 e = null; 153 break; 154 } 155 } 156 if (e != null) { 159 listeners.addLast(e); 160 } 161 162 lowThreshold = generateLowThreshold(); 167 if (lowThreshold < prevLowThreshold) { 168 notifyNewLowThreshold(lowThreshold); 169 } 170 } 171 176 return true; 177 178 } finally { 179 getLogger().info("addListener exit"); 180 } 181 } 182 183 193 public void updateListenerThreshold(Listener listener, int percentage) { 194 getLogger().info("updateListenerThreshold enter"); 195 try { 196 201 202 final long newThreshold = convertPercentageToThreshold(percentage); 203 204 synchronized (listeners) { 205 long prevLowThreshold = generateLowThreshold(); 206 207 Entry e = null; 208 ListIterator <Entry> iter = listeners.listIterator(); 210 while (iter.hasNext()) { 211 e = iter.next(); 212 if (e.listener == listener) { 213 iter.remove(); 214 break; 215 } else { 216 e = null; 217 } 218 } 219 if (e != null) { 221 e.threshold = newThreshold; 222 223 iter = listeners.listIterator(); 225 while (iter.hasNext()) { 226 Entry ee = iter.next(); 227 if (newThreshold <= ee.threshold) { 228 iter.add(e); 229 break; 230 } 231 } 232 lowThreshold = generateLowThreshold(); 233 if (lowThreshold != prevLowThreshold) { 234 notifyNewLowThreshold(lowThreshold); 235 } 236 } 237 } 238 239 244 245 } finally { 246 getLogger().info("updateListenerThreshold exit"); 247 } 248 } 249 250 257 public boolean removeListener(Listener listener) { 258 getLogger().info("removeListener enter"); 259 try { 260 boolean result = false; 261 synchronized (listeners) { 262 long prevLowThreshold = generateLowThreshold(); 263 264 final ListIterator <Entry> iter = listeners.listIterator(); 265 while (iter.hasNext()) { 266 Entry ee = iter.next(); 267 if (listener == ee.listener) { 268 iter.remove(); 269 result = true; 270 break; 271 } 272 } 273 274 lowThreshold = generateLowThreshold(); 276 if (lowThreshold > prevLowThreshold) { 277 notifyNewLowThreshold(lowThreshold); 278 } 279 280 } 281 return result; 282 } finally { 283 getLogger().info("removeListener exit"); 284 } 285 } 286 287 291 public void removeAllListener() { 292 getLogger().info("removeAllListener enter"); 293 try { 294 listeners.clear(); 295 notifyNewLowThreshold(generateLowThreshold()); 296 } finally { 297 getLogger().info("removeAllListener exit"); 298 } 299 } 300 301 309 protected long generateLowThreshold() { 310 return listeners.isEmpty() 313 ? Long.MAX_VALUE 314 : listeners.get(0).threshold; 315 } 316 317 318 324 protected void notifyListeners(final long usedMemory, 325 final long maxMemory) { 326 synchronized (listeners) { 327 for (Entry e : listeners) { 328 if (usedMemory >= e.threshold) { 329 e.listener.memoryUsageNotification(usedMemory, 330 maxMemory); 331 } 332 } 333 } 334 } 335 336 342 protected void notifyNewLowThreshold(final long newLowThreshold) { 343 } 345 346 351 public abstract long getMaxMemory(); 352 353 358 public abstract long getUsedMemory(); 359 360 367 protected long convertPercentageToThreshold(final int percentage) { 368 if (percentage < 0 || percentage > MAX_PERCENTAGE) { 369 throw new IllegalArgumentException ( 370 "Percentage not in range: " +percentage); 371 } 372 373 long maxMemory = getMaxMemory(); 374 long l = (maxMemory * percentage) / MAX_PERCENTAGE; 375 return l; 376 } 377 378 384 protected int convertThresholdToPercentage(final long threshold) { 385 long maxMemory = getMaxMemory(); 386 int i = (int) ((MAX_PERCENTAGE * threshold) / maxMemory); 387 return i; 388 } 389 390 395 protected int usagePercentage() { 396 return convertThresholdToPercentage(getUsedMemory()); 397 } 398 399 public void resetFromTest() { 400 long lowThreshold = generateLowThreshold(); 401 notifyNewLowThreshold(lowThreshold); 402 } 403 } 404 405 | Popular Tags |