001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.activemq.usage;
018
019 /**
020 * Used to keep track of how much of something is being used so that a
021 * productive working set usage can be controlled. Main use case is manage
022 * memory usage.
023 *
024 * @org.apache.xbean.XBean
025 *
026 */
027 public class MemoryUsage extends Usage<MemoryUsage> {
028
029 private long usage;
030
031 public MemoryUsage() {
032 this(null, null);
033 }
034
035 /**
036 * Create the memory manager linked to a parent. When the memory manager is
037 * linked to a parent then when usage increased or decreased, the parent's
038 * usage is also increased or decreased.
039 *
040 * @param parent
041 */
042 public MemoryUsage(MemoryUsage parent) {
043 this(parent, "default");
044 }
045
046 public MemoryUsage(String name) {
047 this(null, name);
048 }
049
050 public MemoryUsage(MemoryUsage parent, String name) {
051 this(parent, name, 1.0f);
052 }
053
054 public MemoryUsage(MemoryUsage parent, String name, float portion) {
055 super(parent, name, portion);
056 }
057
058 /**
059 * @throws InterruptedException
060 */
061 public void waitForSpace() throws InterruptedException {
062 if (parent != null) {
063 parent.waitForSpace();
064 }
065 synchronized (usageMutex) {
066 for (int i = 0; percentUsage >= 100; i++) {
067 usageMutex.wait();
068 }
069 }
070 }
071
072 /**
073 * @param timeout
074 * @throws InterruptedException
075 * @return true if space
076 */
077 public boolean waitForSpace(long timeout) throws InterruptedException {
078 if (parent != null) {
079 if (!parent.waitForSpace(timeout)) {
080 return false;
081 }
082 }
083 synchronized (usageMutex) {
084 if (percentUsage >= 100) {
085 usageMutex.wait(timeout);
086 }
087 return percentUsage < 100;
088 }
089 }
090
091 public boolean isFull() {
092 if (parent != null && parent.isFull()) {
093 return true;
094 }
095 synchronized (usageMutex) {
096 return percentUsage >= 100;
097 }
098 }
099
100 /**
101 * Tries to increase the usage by value amount but blocks if this object is
102 * currently full.
103 *
104 * @param value
105 * @throws InterruptedException
106 */
107 public void enqueueUsage(long value) throws InterruptedException {
108 waitForSpace();
109 increaseUsage(value);
110 }
111
112 /**
113 * Increases the usage by the value amount.
114 *
115 * @param value
116 */
117 public void increaseUsage(long value) {
118 if (value == 0) {
119 return;
120 }
121 int percentUsage;
122 synchronized (usageMutex) {
123 usage += value;
124 percentUsage = caclPercentUsage();
125 }
126 setPercentUsage(percentUsage);
127 if (parent != null) {
128 ((MemoryUsage)parent).increaseUsage(value);
129 }
130 }
131
132 /**
133 * Decreases the usage by the value amount.
134 *
135 * @param value
136 */
137 public void decreaseUsage(long value) {
138 if (value == 0) {
139 return;
140 }
141 int percentUsage;
142 synchronized (usageMutex) {
143 usage -= value;
144 percentUsage = caclPercentUsage();
145 }
146 setPercentUsage(percentUsage);
147 if (parent != null) {
148 parent.decreaseUsage(value);
149 }
150 }
151
152 protected long retrieveUsage() {
153 return usage;
154 }
155
156 public long getUsage() {
157 return usage;
158 }
159
160 public void setUsage(long usage) {
161 this.usage = usage;
162 }
163 }