| 1 | package de.uka.ipd.sdq.probespec.framework.garbagecollection; |
| 2 | |
| 3 | import java.util.HashMap; |
| 4 | import java.util.Map; |
| 5 | |
| 6 | import org.apache.log4j.Logger; |
| 7 | |
| 8 | import de.uka.ipd.sdq.probespec.framework.ISampleBlackboard; |
| 9 | import de.uka.ipd.sdq.probespec.framework.ProbeSetAndRequestContext; |
| 10 | import de.uka.ipd.sdq.probespec.framework.calculator.Calculator; |
| 11 | |
| 12 | /** |
| 13 | * A garbage collector for the {@link ISampleBlackboard}. It cleans up obsolete |
| 14 | * samples stored at the blackboard. |
| 15 | * <p> |
| 16 | * Generally a sample is obsolete if there are no {@link Calculator}s interested |
| 17 | * in the sample anymore. Assuming that calculators are solely interested in |
| 18 | * samples from the same region, all samples belonging to a particular region |
| 19 | * can be cleaned up as soon as it is assured that there will be no new samples |
| 20 | * within that region. |
| 21 | * <p> |
| 22 | * A region can be represented by a thread, a process or something else like |
| 23 | * specified by the class parameter T. |
| 24 | * <p> |
| 25 | * The cleanup starts as soon as the population within a region turns to 0. Then |
| 26 | * it is assumed that there will be no new samples within that region. The |
| 27 | * population is increased by calling {@link #enterRegion(Object)} and decreased |
| 28 | * by calling {@link #leaveRegion(Object)}. |
| 29 | * |
| 30 | * @param <T> |
| 31 | * denotes the type representing regions. |
| 32 | * |
| 33 | * @author Philipp Merkle |
| 34 | * |
| 35 | */ |
| 36 | public abstract class RegionBasedGarbageCollector<T> implements |
| 37 | IRegionBasedGarbageCollector<T> { |
| 38 | |
| 39 | public static Logger logger = Logger |
| 40 | .getLogger(RegionBasedGarbageCollector.class); |
| 41 | |
| 42 | // Counts how often a regions has been entered but not left yet (the |
| 43 | // region's population) |
| 44 | // Maps regionId to process count within region. |
| 45 | private Map<T, Integer> regionCountMap; |
| 46 | |
| 47 | /** |
| 48 | * Default constructor. Constructs a garbage collector for the specified |
| 49 | * blackboard. |
| 50 | * |
| 51 | * @param blackboard |
| 52 | * the blackboard which is to keep clean by the garbage |
| 53 | * collector. |
| 54 | */ |
| 55 | public RegionBasedGarbageCollector() { |
| 56 | // initialise maps |
| 57 | regionCountMap = new HashMap<T, Integer>(); |
| 58 | } |
| 59 | |
| 60 | /** |
| 61 | * Extracts the region id for the specified |
| 62 | * {@link ProbeSetAndRequestContext}. |
| 63 | * |
| 64 | * @param c |
| 65 | * the {@link ProbeSetAndRequestContext} |
| 66 | * @return the extracted region representative |
| 67 | */ |
| 68 | public abstract T obtainRegionId(ProbeSetAndRequestContext c); |
| 69 | |
| 70 | /** |
| 71 | * Informs the garbage collector that the specified region has been entered. |
| 72 | * |
| 73 | * @param regionId |
| 74 | * the id representing the entered region |
| 75 | */ |
| 76 | @Override |
| 77 | public void enterRegion(T regionId) { |
| 78 | if (increasePopulation(regionId) == 1) { |
| 79 | logger.debug("Region " + regionId + " opened."); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Informs the garbage collector that the specified region has been left. |
| 85 | * |
| 86 | * As soon as the population reaches 0, the cleanup starts. |
| 87 | * |
| 88 | * @param regionId |
| 89 | * the id representing the left region |
| 90 | */ |
| 91 | @Override |
| 92 | public void leaveRegion(T regionId) { |
| 93 | if (decreasePopulation(regionId) == 0) { |
| 94 | collectRegionSamples(regionId); |
| 95 | regionCountMap.remove(regionId); |
| 96 | logger.debug("Region " + regionId + " closed."); |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Informs the garbage collector that a new sample has been arrived that |
| 102 | * eventually needs to be collected. Only the observed blackboard should |
| 103 | * call this method. |
| 104 | */ |
| 105 | |
| 106 | /** |
| 107 | * Deletes all probe samples taken within the specified region from the |
| 108 | * blackboard. |
| 109 | * |
| 110 | * @param regionId |
| 111 | * the region id whose probe samples are to be deleted |
| 112 | */ |
| 113 | public abstract void collectRegionSamples(T regionId); |
| 114 | |
| 115 | /** |
| 116 | * Changes the population count of the specified region. |
| 117 | * |
| 118 | * @param regionId |
| 119 | * the id representing the region |
| 120 | * @param amount |
| 121 | * the amount to add (positive value) or subtract (negative |
| 122 | * value) |
| 123 | * @return the changed population count |
| 124 | */ |
| 125 | private int changePopulationCounter(T regionId, int amount) { |
| 126 | int counter = 0; |
| 127 | if (regionCountMap.containsKey(regionId)) { |
| 128 | counter = regionCountMap.get(regionId); |
| 129 | } |
| 130 | counter += amount; |
| 131 | regionCountMap.put(regionId, counter); |
| 132 | return counter; |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * Increases the population count of the specified region by one. |
| 137 | * |
| 138 | * @param regionId |
| 139 | * the id representing the region |
| 140 | * @return the increased population count |
| 141 | */ |
| 142 | private int increasePopulation(T regionId) { |
| 143 | return changePopulationCounter(regionId, 1); |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * Decreases the population count of the specified region by one. |
| 148 | * |
| 149 | * @param regionId |
| 150 | * the id representing the region |
| 151 | * @return the decreased population count |
| 152 | */ |
| 153 | private int decreasePopulation(T regionId) { |
| 154 | return changePopulationCounter(regionId, -1); |
| 155 | } |
| 156 | |
| 157 | } |