001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.monitor;
023:
024: import java.io.Serializable;
025:
026: /**
027: * Simple thread-safe POJO encapsulating locking stats.
028: *
029: * Turned this class to Serializable to be able to
030: * return copies of instances of this class over RMI.
031: *
032: * In this case it becomes detached from the EntityLockMonitor
033: * factory.
034: *
035: * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
036: * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
037: * @version $Revision: 57209 $
038: */
039: public class LockMonitor implements Serializable {
040: // Private -------------------------------------------------------
041:
042: /** @since 4.0.2 */
043: private static final long serialVersionUID = -6710878502772579272L;
044:
045: /* Lock Stats */
046: private long totalTime;
047: private long numContentions;
048: private long timeouts;
049: private long maxContenders;
050: private long currentContenders;
051:
052: /** Back reference to the non-Serializable LockMonitor factory */
053: private transient EntityLockMonitor parent;
054:
055: // Constructors --------------------------------------------------
056:
057: /**
058: * @param parent factory
059: */
060: public LockMonitor(EntityLockMonitor parent) {
061: this .parent = parent;
062: }
063:
064: // Accessors -----------------------------------------------------
065:
066: public synchronized long getTotalTime() {
067: return totalTime;
068: }
069:
070: public synchronized long getNumContentions() {
071: return numContentions;
072: }
073:
074: public synchronized long getTimeouts() {
075: return timeouts;
076: }
077:
078: public synchronized long getMaxContenders() {
079: return maxContenders;
080: }
081:
082: public synchronized long getCurrentContenders() {
083: return currentContenders;
084: }
085:
086: // Modifiers -----------------------------------------------------
087:
088: /**
089: * Adjust the counters to indicate a contetion conditions.
090: *
091: * If the parent EntityLockMonitor has been initialized
092: * the total stats will be updated, as well.
093: */
094: public void contending() {
095: synchronized (this ) {
096: ++numContentions;
097: ++currentContenders;
098:
099: if (currentContenders > maxContenders) {
100: maxContenders = currentContenders;
101: }
102: }
103:
104: // Remark Ulf Schroeter: DO NOT include following call into the
105: // synchronization block because it will cause deadlocks between
106: // LockMonitor methods and EntityLockMonitor.clearMonitor() call!
107: if (parent != null) {
108: parent.incrementContenders();
109: }
110: }
111:
112: /**
113: * Adjust the counters to indicate that contention is over
114: *
115: * If the parent EntityLockMonitor has been initialized
116: * the total stats will be updated, too.
117: */
118: public void finishedContending(long time) {
119: synchronized (this ) {
120: totalTime += time;
121: --currentContenders;
122: }
123:
124: // Remark Ulf Schroeter: DO NOT include following call into the
125: // synchronization block because it will cause deadlocks between
126: // LockMonitor methods and EntityLockMonitor.clearMonitor() call!
127: if (parent != null) {
128: parent.decrementContenders(time);
129: }
130: }
131:
132: /**
133: * Increase the timeouts on this lock
134: */
135: public void increaseTimeouts() {
136: synchronized (this ) {
137: ++timeouts;
138: }
139: }
140:
141: /**
142: * Reset the counters.
143: *
144: * CurrentContenders stays unchanged and
145: * MaxCondenders is set to CurrentContenders
146: */
147: public void reset() {
148: synchronized (this ) {
149: timeouts = 0;
150: totalTime = 0;
151: numContentions = 0;
152: // maxContenders always >= currentContenders
153: maxContenders = currentContenders;
154: }
155: }
156:
157: // Object overrides ----------------------------------------------
158:
159: public String toString() {
160: StringBuffer sbuf = new StringBuffer(128);
161:
162: sbuf.append(super .toString()).append("[ ").append("totalTime=")
163: .append(getTotalTime()).append(", numContentions=")
164: .append(getNumContentions()).append(", timeouts=")
165: .append(getTimeouts()).append(", maxContenders=")
166: .append(getMaxContenders()).append(
167: ", currentContenders=").append(
168: getCurrentContenders()).append(" ]");
169:
170: return sbuf.toString();
171: }
172: }
|