/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.server.util.concurrent;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AlertSerializer {
private final Log log = LogFactory.getLog(AlertSerializer.class);
private static Map<Integer, ReentrantReadWriteLock> locks = new HashMap<Integer, ReentrantReadWriteLock>();
private static Map<Integer, Long> lockTimes = Collections.synchronizedMap(new HashMap<Integer, Long>());
private static AlertSerializer singleton = new AlertSerializer();;
// synchronize so only one thread creates our singleton
public static synchronized AlertSerializer getSingleton() {
return singleton;
}
public void lock(int alertDefinitionId) {
String msg = "tid= " + Thread.currentThread().getId() + ": alertDefinitionId=" + alertDefinitionId;
boolean debug = this.log.isDebugEnabled();
ReentrantReadWriteLock lock = null;
logDebug(debug, msg, ": about to synchronize");
synchronized (this) {
logDebug(debug, msg, ": synchronized");
lock = AlertSerializer.locks.get(alertDefinitionId);
if (lock == null) {
logDebug(debug, msg, ": creating new lock");
lock = new ReentrantReadWriteLock();
AlertSerializer.locks.put(alertDefinitionId, lock);
}
}
logDebug(debug, msg, ": acquiring write lock");
long start = System.currentTimeMillis();
lock.writeLock().lock();
long end = System.currentTimeMillis();
long duration = end - start;
AlertSerializer.lockTimes.put(alertDefinitionId, Long.valueOf(end));
if (duration < 5000L) {
logDebug(debug, msg, ": acquired write lock in millis=" + duration);
} else {
this.log.info(msg + ": acquired write lock in millis=" + duration);
}
return;
}
public void unlock(int alertDefinitionId) {
String msg = "tid= " + Thread.currentThread().getId() + ": alertDefinitionId=" + alertDefinitionId;
boolean debug = this.log.isDebugEnabled();
ReentrantReadWriteLock lock = AlertSerializer.locks.get(alertDefinitionId);
if (lock != null) {
Long lockedTime = AlertSerializer.lockTimes.get(alertDefinitionId);
long duration = System.currentTimeMillis() - ((lockedTime != null) ? lockedTime : Long.MAX_VALUE);
if (duration < 5000L) {
logDebug(debug, msg, ": releasing write lock after being locked for millis=" + duration);
} else {
this.log.info(msg + ": releasing write lock after being locked for millis=" + duration);
}
lock.writeLock().unlock();
logDebug(debug, msg, ": released write lock");
} else {
this.log.warn(msg + ": cannot release write lock");
}
return;
}
private void logDebug(boolean enabled, String arg1, String arg2) {
if (enabled) {
this.log.debug(arg1 + arg2);
}
}
}