/* Copyright (c) 2001 - 2011 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.geoserver; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.util.logging.Logging; /** * The global configuration lock. At the moment it is called by coarse grained request level * callbacks to lock both the GUI and the REST configuration so that concurrent access does not end * up causing issues (like corrupt configuration and the like). * <p> * The locking code can be disabled by calling * {@link GeoServerConfigurationLock#setEnabled(boolean)} or by setting the system variable * {code}-DGeoServerConfigurationLock.enabled=false{code} * * @author Andrea Aime - GeoSolution * */ public class GeoServerConfigurationLock { private static final Level LEVEL = Level.FINE; private static final Logger LOGGER = Logging.getLogger(GeoServerConfigurationLock.class); private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); public static enum LockType { READ, WRITE }; private boolean enabled; public GeoServerConfigurationLock() { String pvalue = System.getProperty("GeoServerConfigurationLock.enabled"); if (pvalue != null) { enabled = Boolean.parseBoolean(pvalue); } else { enabled = true; } LOGGER.info("GeoServer configuration lock is " + (enabled ? "enabled" : "disabled")); } /** * Opens a lock in the specified mode. To avoid deadlocks make sure the corresponding unlock * method is called as well before the code exits * * @param type */ public void lock(LockType type) { if (!enabled) { return; } Lock lock; if (type == LockType.WRITE) { lock = readWriteLock.writeLock(); } else { lock = readWriteLock.readLock(); } if (LOGGER.isLoggable(LEVEL)) { LOGGER.log(LEVEL, "Thread " + Thread.currentThread().getId() + " locking in mode " + type); } lock.lock(); if (LOGGER.isLoggable(LEVEL)) { LOGGER.log(LEVEL, "Thread " + Thread.currentThread().getId() + " got the lock in mode " + type); } } /** * Unlocks a previously acquired lock. The lock type must match the previous * {@link #lock(LockType)} call * * @param type */ public void unlock(LockType type) { if (!enabled) { return; } Lock lock; if (type == LockType.WRITE) { lock = readWriteLock.writeLock(); } else { lock = readWriteLock.readLock(); } if (LOGGER.isLoggable(LEVEL)) { LOGGER.log(LEVEL, "Thread " + Thread.currentThread().getId() + " releasing the lock in mode " + type); } lock.unlock(); } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } }