/* * RHQ Management Platform * Copyright (C) 2005-2012 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 InventoryReportSerializer { private final Log log = LogFactory.getLog(InventoryReportSerializer.class); private static Map<String, ReentrantReadWriteLock> locks = new HashMap<String, ReentrantReadWriteLock>(); private static Map<String, Long> lockTimes = Collections.synchronizedMap(new HashMap<String, Long>()); private static InventoryReportSerializer singleton = new InventoryReportSerializer(); public static InventoryReportSerializer getSingleton() { return singleton; } public void lock(String agentName) { String msg = "tid=" + Thread.currentThread().getId() + "; agent=" + agentName; boolean debug = this.log.isDebugEnabled(); ReentrantReadWriteLock lock = null; logDebug(debug, msg, ": about to synchronize"); synchronized (this) { logDebug(debug, msg, ": synchronized"); lock = InventoryReportSerializer.locks.get(agentName); if (lock == null) { logDebug(debug, msg, ": creating new lock"); lock = new ReentrantReadWriteLock(); InventoryReportSerializer.locks.put(agentName, lock); } } logDebug(debug, msg, ": acquiring write lock"); long start = System.currentTimeMillis(); lock.writeLock().lock(); long end = System.currentTimeMillis(); long duration = end - start; InventoryReportSerializer.lockTimes.put(agentName, 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(String agentName) { String msg = "tid=" + Thread.currentThread().getId() + "; agent=" + agentName; boolean debug = this.log.isDebugEnabled(); ReentrantReadWriteLock lock = InventoryReportSerializer.locks.get(agentName); if (lock != null) { Long lockedTime = InventoryReportSerializer.lockTimes.get(agentName); 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); } } }