Return-Path: Delivered-To: apmail-db-ojb-dev-archive@www.apache.org Received: (qmail 98268 invoked from network); 28 Jan 2006 11:06:55 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 28 Jan 2006 11:06:55 -0000 Received: (qmail 99869 invoked by uid 500); 28 Jan 2006 11:06:52 -0000 Delivered-To: apmail-db-ojb-dev-archive@db.apache.org Received: (qmail 99829 invoked by uid 500); 28 Jan 2006 11:06:51 -0000 Mailing-List: contact ojb-dev-help@db.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "OJB Developers List" Reply-To: "OJB Developers List" Delivered-To: mailing list ojb-dev@db.apache.org Received: (qmail 99818 invoked by uid 500); 28 Jan 2006 11:06:51 -0000 Received: (qmail 99815 invoked by uid 99); 28 Jan 2006 11:06:51 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 28 Jan 2006 03:06:51 -0800 X-ASF-Spam-Status: No, hits=-8.6 required=10.0 tests=ALL_TRUSTED,INFO_TLD,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Sat, 28 Jan 2006 03:06:48 -0800 Received: (qmail 97806 invoked by uid 65534); 28 Jan 2006 11:06:28 -0000 Message-ID: <20060128110627.97778.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r373136 - in /db/ojb/branches/OJB_1_0_RELEASE/src: java/org/apache/ojb/broker/locking/ test/org/apache/ojb/ Date: Sat, 28 Jan 2006 11:05:58 -0000 To: ojb-commits@db.apache.org From: arminw@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: arminw Date: Sat Jan 28 03:05:34 2006 New Revision: 373136 URL: http://svn.apache.org/viewcvs?rev=373136&view=rev Log: fix OJB-89 fix problems with too early released read-locks fix remote lock manager, add new properties Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolation.java db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolationManager.java db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManager.java db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerCommonsImpl.java db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerRemoteImpl.java db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerServlet.java db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/web.xml Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolation.java URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolation.java?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolation.java (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolation.java Sat Jan 28 03:05:34 2006 @@ -1,5 +1,7 @@ package org.apache.ojb.broker.locking; +import java.io.Serializable; + /* Copyright 2002-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +22,7 @@ * This interface defines method that a Locking Strategy must implement * according to the isolation level it represents. */ -abstract class LockIsolation +abstract class LockIsolation implements Serializable { /** * Returns the isolation level identity. Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolationManager.java URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolationManager.java?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolationManager.java (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockIsolationManager.java Sat Jan 28 03:05:34 2006 @@ -15,14 +15,14 @@ * limitations under the License. */ - +import java.io.Serializable; /** * Factory class used to obtain the proper {@link LockIsolation} level. * * @version $Id$ */ -class LockIsolationManager +class LockIsolationManager implements Serializable { private LockIsolation readUncommitedStrategy; private LockIsolation readCommitedStrategy; Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManager.java URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManager.java?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManager.java (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManager.java Sat Jan 28 03:05:34 2006 @@ -52,15 +52,16 @@ /** * The maximal time to wait for acquire a lock. * - * @return + * @return The time to wait for aquire a lock in milliseconds. */ public long getBlockTimeout(); /** - * Set the maximal time to wait for acquire a lock in milliseconds. + * Set the maximal time to wait for acquire a lock. + *
* All so called non-blocking implementation will ignore this setting. * - * @param timeout The time to wait for acquire a lock. + * @param timeout The time to wait for acquire a lock in milliseconds. */ public void setBlockTimeout(long timeout); Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerCommonsImpl.java URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerCommonsImpl.java?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerCommonsImpl.java (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerCommonsImpl.java Sat Jan 28 03:05:34 2006 @@ -22,6 +22,9 @@ import org.apache.commons.transaction.util.LoggerFacade; import org.apache.ojb.broker.util.logging.Logger; import org.apache.ojb.broker.util.logging.LoggerFactory; +import org.apache.ojb.broker.util.configuration.Configurable; +import org.apache.ojb.broker.util.configuration.Configuration; +import org.apache.ojb.broker.util.configuration.ConfigurationException; /** * A {@link LockManager} implementation based on apache's commons-transaction @@ -33,7 +36,7 @@ * @author Armin Waibel * @version $Id$ */ -public class LockManagerCommonsImpl implements LockManager +public class LockManagerCommonsImpl implements LockManager, Configurable { private Logger log = LoggerFactory.getLogger(LockManagerCommonsImpl.class); @@ -45,17 +48,19 @@ * Time to wait when lock call is blocked. */ private long blockTimeout; - private LoggerFacade logFacade; private OJBLockManager lm; public LockManagerCommonsImpl() { - logFacade = new LoggerFacadeImpl(); // default lock timeout this.lockTimeout = DEFAULT_LOCK_TIMEOUT; // default time to wait for a lock this.blockTimeout = DEFAULT_BLOCK_TIMEOUT; - lm = new OJBLockManager(logFacade, blockTimeout, GenericLockManager.DEFAULT_CHECK_THRESHHOLD); + lm = new OJBLockManager(new LoggerFacadeImpl(), blockTimeout, GenericLockManager.DEFAULT_CHECK_THRESHHOLD); + } + + public void configure(Configuration pConfig) throws ConfigurationException + { } private boolean ignore(int isolationLevel) @@ -87,26 +92,26 @@ { String eol = SystemUtils.LINE_SEPARATOR; StringBuffer msg = new StringBuffer("Class: " + LockManagerCommonsImpl.class.getName() + eol); - msg.append("lock timeout: " + getLockTimeout() + " [ms]" + eol); - msg.append("block timeout: " + getBlockTimeout() + " [ms]" + eol); - msg.append("commons-tx lock-manger info ==> " + eol); + msg.append("lock timeout: ").append(getLockTimeout()).append(" [ms]").append(eol); + msg.append("block timeout: ").append(getBlockTimeout()).append(" [ms]").append(eol); + msg.append("commons-tx lock-manger info ==> ").append(eol); msg.append(lm); return msg.toString(); } public boolean readLock(Object key, Object resourceId, int isolationLevel) { - return ignore(isolationLevel) ? true : lm.readLock(key, resourceId, new Integer(isolationLevel), blockTimeout); + return ignore(isolationLevel) || lm.readLock(key, resourceId, new Integer(isolationLevel), blockTimeout); } public boolean writeLock(Object key, Object resourceId, int isolationLevel) { - return ignore(isolationLevel) ? true : lm.writeLock(key, resourceId, new Integer(isolationLevel), blockTimeout); + return ignore(isolationLevel) || lm.writeLock(key, resourceId, new Integer(isolationLevel), blockTimeout); } public boolean upgradeLock(Object key, Object resourceId, int isolationLevel) { - return ignore(isolationLevel) ? true : lm.upgradeLock(key, resourceId, new Integer(isolationLevel), blockTimeout); + return ignore(isolationLevel) || lm.upgradeLock(key, resourceId, new Integer(isolationLevel), blockTimeout); } public boolean releaseLock(Object key, Object resourceId) Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java Sat Jan 28 03:05:34 2006 @@ -16,15 +16,19 @@ */ import java.io.Serializable; -import java.util.Collection; import java.util.HashMap; -import java.util.Hashtable; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.LinkedHashMap; +import org.apache.commons.collections.list.TreeList; +import org.apache.commons.lang.SystemUtils; +import org.apache.ojb.broker.util.configuration.Configurable; +import org.apache.ojb.broker.util.configuration.Configuration; +import org.apache.ojb.broker.util.configuration.ConfigurationException; import org.apache.ojb.broker.util.logging.Logger; import org.apache.ojb.broker.util.logging.LoggerFactory; -import org.apache.commons.lang.SystemUtils; /** * This implementation of the {@link LockManager} interface supports a simple, fast, non-blocking @@ -32,18 +36,21 @@ * * @version $Id$ */ -public class LockManagerInMemoryImpl implements LockManager +public class LockManagerInMemoryImpl implements LockManager, Configurable, Serializable { - private Logger log = LoggerFactory.getLogger(LockManagerInMemoryImpl.class); - private static long CLEANUP_FREQUENCY = 1000; // 1000 milliseconds. - private static int MAX_LOCKS_TO_CLEAN = 300; + private transient Logger log; + /** The period to search for timed out locks. */ + private long cleanupFrequency = 10000; // milliseconds. + /** The number of lock entries to check for timeout */ + private int maxLocksToClean = 500; /** * MBAIRD: a LinkedHashMap returns objects in the order you put them in, * while still maintaining an O(1) lookup like a normal hashmap. We can then * use this to get the oldest entries very quickly, makes cleanup a breeze. */ - private HashMap locktable = new HashMap(); - private LockIsolationManager lockStrategyManager = new LockIsolationManager(); + private final Map resourceLockMap = new LinkedHashMap(70); + private final Map keyLockMap = new HashMap(); + private final LockIsolationManager lockStrategyManager = new LockIsolationManager(); private long m_lastCleanupAt = System.currentTimeMillis(); private long lockTimeout; private long timeoutCounterRead; @@ -54,6 +61,53 @@ this.lockTimeout = DEFAULT_LOCK_TIMEOUT; } + public void configure(Configuration pConfig) throws ConfigurationException + { + } + + private Logger getLog() + { + if(log == null) + { + log = LoggerFactory.getLogger(LockManagerInMemoryImpl.class); + } + return log; + } + + /** The period to search for timed out locks. */ + public long getCleanupFrequency() + { + return cleanupFrequency; + } + + /** Set the period to search for timed out locks. */ + public void setCleanupFrequency(long cleanupFrequency) + { + this.cleanupFrequency = cleanupFrequency; + } + + /** + * The number of lock entries to check for timeout + * on each lock cleanup run. + * + * @see #getCleanupFrequency() + */ + public int getMaxLocksToClean() + { + return maxLocksToClean; + } + + /** + * Set the number of lock entries to check for timeout + * on each lock cleanup run. + * + * @see #setCleanupFrequency(long) + */ + public void setMaxLocksToClean(int maxLocksToClean) + { + this.maxLocksToClean = maxLocksToClean; + } + public long getLockTimeout() { return lockTimeout; @@ -66,6 +120,7 @@ /** * NOOP + * * @return Always '0' */ public long getBlockTimeout() @@ -73,399 +128,175 @@ return 0; } - /** - * NOOP - */ + /** NOOP */ public void setBlockTimeout(long timeout) { + getLog().info("block-timeout setting is not supported"); } public String getLockInfo() { + // synchronize locks before return locking information + checkTimedOutLocks(); + String eol = SystemUtils.LINE_SEPARATOR; StringBuffer msg = new StringBuffer("Class: " + LockManagerInMemoryImpl.class.getName() + eol); - msg.append("lock timeout: " + getLockTimeout() + " [ms]" + eol); - msg.append("concurrent lock owners: " + locktable.size() + eol); - msg.append("timed out write locks: " + timeoutCounterWrite + eol); - msg.append("timed out read locks: " + timeoutCounterRead + eol); + msg.append("lock timeout: ").append(getLockTimeout()).append(" [ms]").append(eol); + msg.append("cleanup frequency: ").append(getCleanupFrequency()).append(" [ms]").append(eol); + msg.append("max locks to clean: ").append(getMaxLocksToClean()).append(eol); + msg.append(eol); + msg.append("lock map size: ").append(resourceLockMap.size()).append(eol); + msg.append("timed out write locks: ").append(timeoutCounterWrite).append(eol); + msg.append("timed out read locks: ").append(timeoutCounterRead).append(eol); return msg.toString(); } - public boolean readLock(Object key, Object resourceId, int isolationLevel) + public boolean readLock(final Object key, final Object resourceId, final int isolationLevel) { - if(log.isDebugEnabled()) log.debug("LM.readLock(tx-" + key + ", " + resourceId + ")"); + if(getLog().isDebugEnabled()) getLog().debug("LM.readLock(tx-" + key + ", " + resourceId + ")"); checkTimedOutLocks(); LockEntry reader = new LockEntry(resourceId, key, System.currentTimeMillis(), - isolationLevel, LockEntry.LOCK_READ); LockIsolation ls = lockStrategyManager.getStrategyFor(isolationLevel); - return addReaderIfPossibleInternal(reader, ls.allowMultipleRead(), ls.allowReadWhenWrite()); - } - private boolean addReaderIfPossibleInternal(LockEntry reader, boolean allowMultipleReader, - boolean allowReaderWhenWriteLock) - { - boolean result = false; - ObjectLocks objectLocks = null; - Object oid = reader.getResourceId(); + boolean result; + ObjectLocks objectLocks; /** * MBAIRD: We need to synchronize the get/put so we don't have two threads * competing to check if something is locked and double-locking it. */ - synchronized(locktable) + synchronized(resourceLockMap) { - objectLocks = (ObjectLocks) locktable.get(oid); + objectLocks = (ObjectLocks) resourceLockMap.get(resourceId); if(objectLocks == null) { // no write or read lock, go on - objectLocks = new ObjectLocks(); - locktable.put(oid, objectLocks); - objectLocks.addReader(reader); - result = true; - } - else - { - // ObjectLocks exist, first check for a write lock - LockEntry writer = objectLocks.getWriter(); - if(writer != null) - { - // if writer is owned by current entity, read lock is - // successful (we have an write lock) - if(writer.isOwnedBy(reader.getKey())) - { - result = true; - } - else - { - // if read lock is allowed when different entity hold write lock - // go on if multiple reader allowed, else do nothing - if(allowReaderWhenWriteLock && allowMultipleReader) - { - objectLocks.addReader(reader); - result = true; - } - else - { - result = false; - } - } - } - else - { - // no write lock exist, check for existing read locks - if(objectLocks.getReaders().size() > 0) - { - // if we have already an read lock, do nothing - if(objectLocks.getReader(reader.getKey()) != null) - { - result = true; - } - else - { - // we have read locks of other entities, add read lock - // if allowed - if(allowMultipleReader) - { - objectLocks.addReader(reader); - result = true; - } - } - } - else - { - // no read locks exist, so go on - objectLocks.addReader(reader); - result = true; - } - } - } - } - return result; - } - - /** - * Remove an read lock. - */ - public boolean removeReader(Object key, Object resourceId) - { - boolean result = false; - ObjectLocks objectLocks = null; - synchronized(locktable) - { - objectLocks = (ObjectLocks) locktable.get(resourceId); - if(objectLocks != null) - { - /** - * MBAIRD, last one out, close the door and turn off the lights. - * if no locks (readers or writers) exist for this object, let's remove - * it from the locktable. - */ - Map readers = objectLocks.getReaders(); - result = readers.remove(key) != null; - if((objectLocks.getWriter() == null) && (readers.size() == 0)) - { - locktable.remove(resourceId); - } + objectLocks = new ObjectLocks(resourceId); + resourceLockMap.put(resourceId, objectLocks); } + result = objectLocks.addReader(reader, ls.allowMultipleRead(), ls.allowReadWhenWrite()); + if(result) associateKeyWithObjectLock(reader.getKey(), objectLocks); } return result; } - /** - * Remove an write lock. - */ - public boolean removeWriter(Object key, Object resourceId) + public boolean releaseLock(final Object key, final Object resourceId) { - boolean result = false; - ObjectLocks objectLocks = null; - synchronized(locktable) - { - objectLocks = (ObjectLocks) locktable.get(resourceId); - if(objectLocks != null) - { - /** - * MBAIRD, last one out, close the door and turn off the lights. - * if no locks (readers or writers) exist for this object, let's remove - * it from the locktable. - */ - LockEntry entry = objectLocks.getWriter(); - if(entry != null && entry.isOwnedBy(key)) - { - objectLocks.setWriter(null); - result = true; - - // no need to check if writer is null, we just set it. - if(objectLocks.getReaders().size() == 0) - { - locktable.remove(resourceId); - } - } - } - } - return result; - } + if(getLog().isDebugEnabled()) getLog().debug("LM.releaseLock(tx-" + key + ", " + resourceId + ")"); - public boolean releaseLock(Object key, Object resourceId) - { - if(log.isDebugEnabled()) log.debug("LM.releaseLock(tx-" + key + ", " + resourceId + ")"); - boolean result = removeReader(key, resourceId); - // if no read lock could be removed, try write lock - if(!result) + synchronized(resourceLockMap) { - result = removeWriter(key, resourceId); + ObjectLocks lock = (ObjectLocks) resourceLockMap.get(resourceId); + return lock != null && lock.releaseLock(key); } - return result; } - /** - * @see LockManager#releaseLocks(Object) - */ - public void releaseLocks(Object key) + /** @see LockManager#releaseLocks(Object) */ + public void releaseLocks(final Object key) { - if(log.isDebugEnabled()) log.debug("LM.releaseLocks(tx-" + key + ")"); + if(getLog().isDebugEnabled()) getLog().debug("LM.releaseLocks(tx-" + key + ")"); checkTimedOutLocks(); - releaseLocksInternal(key); + doReleaseLocks(key); + //System.out.println("resourceLockMap: " + resourceLockMap.size()); + //System.out.println("keyLockMap: " + keyLockMap.size()); } - private void releaseLocksInternal(Object key) + public boolean writeLock(final Object key, final Object resourceId, final int isolationLevel) { - synchronized(locktable) - { - Collection values = locktable.values(); - ObjectLocks entry; - for(Iterator iterator = values.iterator(); iterator.hasNext();) - { - entry = (ObjectLocks) iterator.next(); - entry.removeReader(key); - if(entry.getWriter() != null && entry.getWriter().isOwnedBy(key)) - { - entry.setWriter(null); - } - } - } - } - - public boolean writeLock(Object key, Object resourceId, int isolationLevel) - { - if(log.isDebugEnabled()) log.debug("LM.writeLock(tx-" + key + ", " + resourceId + ")"); + if(getLog().isDebugEnabled()) getLog().debug("LM.writeLock(tx-" + key + ", " + resourceId + ")"); checkTimedOutLocks(); LockEntry writer = new LockEntry(resourceId, key, System.currentTimeMillis(), - isolationLevel, LockEntry.LOCK_WRITE); LockIsolation ls = lockStrategyManager.getStrategyFor(isolationLevel); - return setWriterIfPossibleInternal(writer, ls.allowWriteWhenRead()); - } - private boolean setWriterIfPossibleInternal(LockEntry writer, boolean allowReaders) - { - boolean result = false; - ObjectLocks objectLocks = null; + boolean result; + ObjectLocks objectLocks; /** * MBAIRD: We need to synchronize the get/put so we don't have two threads * competing to check if something is locked and double-locking it. */ - synchronized(locktable) + synchronized(resourceLockMap) { - objectLocks = (ObjectLocks) locktable.get(writer.getResourceId()); + objectLocks = (ObjectLocks) resourceLockMap.get(resourceId); // if we don't upgrade, go on if(objectLocks == null) { // no locks for current entity exist, so go on - objectLocks = new ObjectLocks(); - objectLocks.setWriter(writer); - locktable.put(writer.getResourceId(), objectLocks); - result = true; - } - else - { - // the ObjectLock exist, check if there is already a write lock - LockEntry oldWriter = objectLocks.getWriter(); - if(oldWriter != null) - { - // if already a write lock exists, check owner - if(oldWriter.isOwnedBy(writer.getKey())) - { - // if current entity has already a write lock - // signal success - result = true; - } - } - else - { - // current ObjectLock has no write lock, so check for readers - int readerSize = objectLocks.getReaders().size(); - if(readerSize > 0) - { - // does current entity have already an read lock - if(objectLocks.getReader(writer.getKey()) != null) - { - if(readerSize == 1) - { - // only current entity has a read lock, so go on - objectLocks.readers.remove(writer.getKey()); - objectLocks.setWriter(writer); - result = true; - } - else - { - // current entity and others have already a read lock - // if aquire a write is allowed, go on - if(allowReaders) - { - objectLocks.readers.remove(writer.getKey()); - objectLocks.setWriter(writer); - result = true; - } - } - } - else - { - // current entity has no read lock, but others - // if aquire a write is allowed, go on - if(allowReaders) - { - objectLocks.setWriter(writer); - result = true; - } - } - } - else - { - // no readers and writers, so go on if we don't upgrade - objectLocks.setWriter(writer); - result = true; - } - } + objectLocks = new ObjectLocks(resourceId); + resourceLockMap.put(resourceId, objectLocks); } + result = objectLocks.addWriter(writer, ls.allowWriteWhenRead()); + if(result) associateKeyWithObjectLock(writer.getKey(), objectLocks); } return result; } - public boolean upgradeLock(Object key, Object resourceId, int isolationLevel) + public boolean upgradeLock(final Object key, final Object resourceId, final int isolationLevel) { - if(log.isDebugEnabled()) log.debug("LM.upgradeLock(tx-" + key + ", " + resourceId + ")"); + if(getLog().isDebugEnabled()) getLog().debug("LM.upgradeLock(tx-" + key + ", " + resourceId + ")"); return writeLock(key, resourceId, isolationLevel); } - /** - * @see LockManager#hasWrite(Object, Object) - */ - public boolean hasWrite(Object key, Object resourceId) + /** @see LockManager#hasWrite(Object, Object) */ + public boolean hasWrite(final Object key, final Object resourceId) { - if(log.isDebugEnabled()) log.debug("LM.hasWrite(tx-" + key + ", " + resourceId + ")"); + if(getLog().isDebugEnabled()) getLog().debug("LM.hasWrite(tx-" + key + ", " + resourceId + ")"); checkTimedOutLocks(); - return hasWriteLockInternal(resourceId, key); - } - private boolean hasWriteLockInternal(Object resourceId, Object key) - { - boolean result = false; - ObjectLocks objectLocks = null; - synchronized(locktable) + ObjectLocks objectLocks; + synchronized(resourceLockMap) { - objectLocks = (ObjectLocks) locktable.get(resourceId); + objectLocks = (ObjectLocks) resourceLockMap.get(resourceId); if(objectLocks != null) { - LockEntry writer = objectLocks.getWriter(); - if(writer != null) - { - result = writer.isOwnedBy(key); - } + return objectLocks.hasWriteLock(key); } } - return result; + return false; } - public boolean hasUpgrade(Object key, Object resourceId) + public boolean hasUpgrade(final Object key, final Object resourceId) { - if(log.isDebugEnabled()) log.debug("LM.hasUpgrade(tx-" + key + ", " + resourceId + ")"); + if(getLog().isDebugEnabled()) getLog().debug("LM.hasUpgrade(tx-" + key + ", " + resourceId + ")"); return hasWrite(key, resourceId); } - /** - * @see LockManager#hasRead(Object, Object) - */ - public boolean hasRead(Object key, Object resourceId) + /** @see LockManager#hasRead(Object, Object) */ + public boolean hasRead(final Object key, final Object resourceId) { - if(log.isDebugEnabled()) log.debug("LM.hasRead(tx-" + key + ", " + resourceId + ')'); + if(getLog().isDebugEnabled()) getLog().debug("LM.hasRead(tx-" + key + ", " + resourceId + ')'); checkTimedOutLocks(); - return hasReadLockInternal(resourceId, key); - } - private boolean hasReadLockInternal(Object resourceId, Object key) - { - boolean result = false; - ObjectLocks objectLocks = null; - synchronized(locktable) + ObjectLocks objectLocks; + synchronized(resourceLockMap) { - objectLocks = (ObjectLocks) locktable.get(resourceId); + objectLocks = (ObjectLocks) resourceLockMap.get(resourceId); if(objectLocks != null) { - LockEntry reader = objectLocks.getReader(key); - if(reader != null || (objectLocks.getWriter() != null && objectLocks.getWriter().isOwnedBy(key))) - { - result = true; - } + return objectLocks.hasReadLock(key); } } - return result; + return false; } /** - * + * The number of locked objects. */ public int lockedObjects() { - return locktable.size(); + return resourceLockMap.size(); } + /** + * Internal method to detect and remove timed out locks. + */ private void checkTimedOutLocks() { - if(System.currentTimeMillis() - m_lastCleanupAt > CLEANUP_FREQUENCY) + if(System.currentTimeMillis() - m_lastCleanupAt > cleanupFrequency) { removeTimedOutLocks(getLockTimeout()); m_lastCleanupAt = System.currentTimeMillis(); @@ -474,24 +305,22 @@ /** * removes all timed out lock entries from the persistent storage. - * The timeout value can be set in the OJB properties file. */ private void removeTimedOutLocks(long timeout) { int count = 0; long maxAge = System.currentTimeMillis() - timeout; - boolean breakFromLoop = false; - ObjectLocks temp = null; - synchronized(locktable) + ObjectLocks temp; + synchronized(resourceLockMap) { - Iterator it = locktable.values().iterator(); + Iterator it = resourceLockMap.values().iterator(); /** * run this loop while: * - we have more in the iterator * - the breakFromLoop flag hasn't been set * - we haven't removed more than the limit for this cleaning iteration. */ - while(it.hasNext() && !breakFromLoop && (count <= MAX_LOCKS_TO_CLEAN)) + while(it.hasNext() && (count <= maxLocksToClean)) { temp = (ObjectLocks) it.next(); if(temp.getWriter() != null) @@ -503,32 +332,54 @@ ++timeoutCounterWrite; } } - if(temp.getYoungestReader() < maxAge) + if(temp.readers != null && temp.readers.size() > 0) { // all readers are older than timeout. - temp.getReaders().clear(); - ++timeoutCounterRead; - if(temp.getWriter() == null) + if(temp.lastReader < maxAge) { - // all readers and writer are older than timeout, - // remove the objectLock from the iterator (which - // is backed by the map, so it will be removed. - it.remove(); + timeoutCounterRead += temp.getReaders().size(); + if(temp.getWriter() == null) + { + // all readers and writer are older than timeout, + // remove the objectLock from the iterator (which + // is backed by the map, so it will be removed. + it.remove(); + } + else + { + temp.getReaders().clear(); + } + } + else + { + // there are outdated read locks + if(temp.eldestReader < maxAge) + { + // we need to walk each reader. + Iterator readerIt = temp.getReaders().values().iterator(); + LockEntry readerLock; + while(readerIt.hasNext()) + { + readerLock = (LockEntry) readerIt.next(); + if(readerLock.getTimestamp() < maxAge) + { + // this read lock is old, remove it. + readerIt.remove(); + ++timeoutCounterRead; + } + } + } + else + { + // nothing to do + } } } else { - // we need to walk each reader. - Iterator readerIt = temp.getReaders().values().iterator(); - LockEntry readerLock = null; - while(readerIt.hasNext()) + if(temp.getWriter() == null) { - readerLock = (LockEntry) readerIt.next(); - if(readerLock.getTimestamp() < maxAge) - { - // this read lock is old, remove it. - readerIt.remove(); - } + it.remove(); } } count++; @@ -536,168 +387,294 @@ } } + private void associateKeyWithObjectLock(Object key, ObjectLocks lock) + { + List list = (List) keyLockMap.get(key); + if(list == null) + { + list = new TreeList(); + keyLockMap.put(key, list); + } + if(!list.contains(lock)) list.add(lock); + } + + private void doReleaseLocks(Object key) + { + synchronized(resourceLockMap) + { + List list = (List) keyLockMap.get(key); + if(list != null) + { + for(int i = 0; i < list.size(); i++) + { + ObjectLocks lock = (ObjectLocks) list.get(i); + lock.releaseLock(key); + if(lock.isEmpty()) resourceLockMap.remove(lock.getResourceId()); + } + keyLockMap.remove(key); + } + } + } + //=============================================================== // inner class //=============================================================== - static final class ObjectLocks + private static final class ObjectLocks implements Serializable { private LockEntry writer; - private Hashtable readers; - private long m_youngestReader = 0; + private Map readers; + private Object resourceId; + private long lastReader = 0; + private long eldestReader = Long.MAX_VALUE; + + ObjectLocks(Object resourceId) + { + this.resourceId = resourceId; + } - ObjectLocks() + private void newReaderMap() { - this(null); + this.readers = new HashMap(); } - ObjectLocks(LockEntry writer) + boolean isEmpty() { - this.writer = writer; - readers = new Hashtable(); + return writer == null && (readers == null || readers.size() == 0); + } + + boolean releaseLock(Object key) + { + if(writer != null && writer.isOwnedBy(key)) + { + writer = null; + return true; + } + else if(readers != null) + { + return readers.remove(key) != null; + } + return false; + } + + public Object getResourceId() + { + return resourceId; + } + + boolean addWriter(LockEntry writer, boolean allowReaders) + { + boolean result = false; + if(this.writer != null) + { + result = this.writer.isOwnedBy(writer.getKey()); + } + else // writer was not set + { + // current ObjectLock has no write lock, so check for readers + int readerSize = readers != null ? readers.size() : 0; + if(readerSize > 0) + { + // does current entity have already an read lock + if(getReader(writer.getKey()) != null) + { + if(readerSize == 1) + { + // only current entity has a read lock, so go on + setWriter(writer); + removeReader(this.writer.getKey()); + result = true; + } + else + { + // current entity and others have already a read lock + // if aquire a write is allowed, go on + if(allowReaders) + { + setWriter(writer); + removeReader(this.writer.getKey()); + result = true; + } + } + } + else + { + // current entity has no read lock, but others + // if aquire a write is allowed, go on + if(allowReaders) + { + setWriter(writer); + result = true; + } + } + } + else + { + setWriter(writer); + result = true; + } + } + return result; } LockEntry getWriter() { - return writer; + return this.writer; + } + + boolean hasWriteLock(Object key) + { + return writer != null && writer.isOwnedBy(key); } - void setWriter(LockEntry writer) + private void setWriter(LockEntry writer) { this.writer = writer; + if(this.writer != null) this.resourceId = writer.getResourceId(); } - Hashtable getReaders() + Map getReaders() { return readers; } - void addReader(LockEntry reader) + boolean hasReadLock(Object key) { - /** - * MBAIRD: - * we want to track the youngest reader so we can remove all readers at timeout - * if the youngestreader is older than the timeoutperiod. - */ - if((reader.getTimestamp() < m_youngestReader) || (m_youngestReader == 0)) + if(writer != null) + { + return writer.isOwnedBy(key); + } + else if(readers != null) + { + LockEntry lock = (LockEntry) readers.get(key); + return lock != null && lock.isOwnedBy(key); + } + return false; + } + + boolean addReader(LockEntry reader, boolean allowMultipleReader, boolean allowReaderWhenWriteLock) + { + if(writer == null) { - m_youngestReader = reader.getTimestamp(); + return internalAddReader(reader, allowMultipleReader); } - this.readers.put(reader.getKey(), reader); + else if(writer.isOwnedBy(reader.getKey())) + { + return true; + } + else if(allowReaderWhenWriteLock) + { + return internalAddReader(reader, allowMultipleReader); + } + return false; } - long getYoungestReader() + private boolean internalAddReader(LockEntry reader, boolean allowMultipleReader) { - return m_youngestReader; + boolean result = true; + if(readers == null) + { + newReaderMap(); + readers.put(reader.getKey(), reader); + } + else if(readers.size() == 0) + { + readers.put(reader.getKey(), reader); + } + else + { + if(this.readers.get(reader.getKey()) != null) + { + } + else if(allowMultipleReader) + { + this.readers.put(reader.getKey(), reader); + } + else + { + result = false; + } + } + if(result) + { + if(reader.timestamp > lastReader) lastReader = reader.timestamp; + if(reader.timestamp < eldestReader) eldestReader = reader.timestamp; + } + return result; } LockEntry getReader(Object key) { - return (LockEntry) this.readers.get(key); + return this.readers != null ? (LockEntry) this.readers.get(key) : null; } LockEntry removeReader(Object key) { - return (LockEntry) this.readers.remove(key); + return this.readers != null ? (LockEntry) this.readers.remove(key) : null; } } - //=============================================================== // inner class //=============================================================== - /** - * A lock entry encapsulates locking information. - */ - final class LockEntry implements Serializable + + /** A lock entry encapsulates locking information. */ + private static final class LockEntry implements Serializable { - /** - * marks a Read Lock. - */ + /** marks a Read Lock. */ static final int LOCK_READ = 0; - /** - * marks a Write Lock. - */ + /** marks a Write Lock. */ static final int LOCK_WRITE = 1; - /** - * the object to be locked. - */ + /** the object to be locked. */ private Object resourceId; - /** - * key for locked object - */ + /** key for locked object */ private Object key; - /** - * the timestamp marking the time of acquisition of this lock - */ + /** the timestamp marking the time of acquisition of this lock */ private long timestamp; /** - * the isolationlevel for this lock. - */ - private int isolationLevel; - - /** * marks if this is a read or a write lock. * LOCK_READ = 0; * LOCK_WRITE = 1; */ private int lockType; - /** - * Multiargument constructor for fast loading of LockEntries by OJB. - */ + /** Multiargument constructor for fast loading of LockEntries by OJB. */ public LockEntry(Object resourceId, Object key, long timestamp, - int isolationLevel, int lockType) { this.resourceId = resourceId; this.key = key; this.timestamp = timestamp; - this.isolationLevel = isolationLevel; this.lockType = lockType; } - /** - * Returns the resource id of the locked object (or the locked object itself). - */ + /** Returns the resource id of the locked object (or the locked object itself). */ public Object getResourceId() { return resourceId; } - /** - * Returns lock key. - */ + /** Returns lock key. */ public Object getKey() { return key; } - /** - * returns the timestamp of the acqusition of the lock. - */ + /** returns the timestamp of the acqusition of the lock. */ public long getTimestamp() { return timestamp; } /** - * returns the isolation level of this lock - */ - public int getIsolationLevel() - { - return isolationLevel; - } - - /** * returns the locktype of this lock. * * @return LOCK_READ if lock is a readlock, @@ -718,23 +695,10 @@ this.lockType = locktype; } - /** - * Returns true if this lock is owned by the specified key. - */ + /** Returns true if this lock is owned by the specified key. */ public boolean isOwnedBy(Object key) { return this.getKey().equals(key); - } - - - /** - * Sets the isolationLevel. - * - * @param isolationLevel The isolationLevel to set - */ - public void setIsolationLevel(int isolationLevel) - { - this.isolationLevel = isolationLevel; } /** Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerRemoteImpl.java URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerRemoteImpl.java?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerRemoteImpl.java (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerRemoteImpl.java Sat Jan 28 03:05:34 2006 @@ -22,11 +22,15 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.io.InputStreamReader; +import java.io.BufferedReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang.SystemUtils; import org.apache.ojb.broker.util.configuration.Configurable; import org.apache.ojb.broker.util.configuration.Configuration; import org.apache.ojb.broker.util.configuration.ConfigurationException; @@ -37,8 +41,8 @@ * This implementation of the {@link LockManager} interface supports locking * in distributed environments in combination with a specific lock servlet. * - * @see LockManagerServlet * @version $Id$ + * @see LockManagerServlet */ public class LockManagerRemoteImpl implements LockManager, Configurable { @@ -64,9 +68,7 @@ { } - /** - * @see org.apache.ojb.broker.util.configuration.Configurable#configure(org.apache.ojb.broker.util.configuration.Configuration) - */ + /** @see org.apache.ojb.broker.util.configuration.Configurable#configure(org.apache.ojb.broker.util.configuration.Configuration) */ public void configure(Configuration pConfig) throws ConfigurationException { String url = pConfig.getString("LockServletUrl", "http://127.0.0.1:8080/ojb-lockserver"); @@ -84,20 +86,12 @@ /** * noop + * * @param timeout */ public void setLockTimeout(long timeout) { -// LockInfo info = new LockInfo(timeout, METHOD_LOCK_TIMEOUT_SET); -// try -// { -// byte[] requestBarr = serialize(info); -// performRequestObject(requestBarr); -// } -// catch(Throwable t) -// { -// throw new LockRuntimeException("Can't set locking timeout", t); -// } + log.info("Can't set lock-timeout, it's managed by the lock-servlet"); } public long getLockTimeout() @@ -110,6 +104,15 @@ } catch(Throwable t) { + Throwable tmp = ExceptionUtils.getRootCause(t); + if(tmp != null) + { + tmp.printStackTrace(); + } + else + { + t.printStackTrace(); + } throw new LockRuntimeException("Can't get locking info", t); } } @@ -128,21 +131,10 @@ } } - /** - * noop - */ + /** noop */ public void setBlockTimeout(long timeout) { -// LockInfo info = new LockInfo(timeout, METHOD_BLOCK_TIMEOUT_SET); -// try -// { -// byte[] requestBarr = serialize(info); -// performRequestObject(requestBarr); -// } -// catch(Throwable t) -// { -// throw new LockRuntimeException("Can't set block timeout value", t); -// } + log.info("Can't set lock-timeout, it's managed by the lock-servlet"); } public String getLockInfo() @@ -189,21 +181,6 @@ } } -// public boolean removeReader(Object key, Object resourceId) -// { -// LockInfo info = new LockInfo(key, resourceId, METHOD_RELEASE_SINGLE_LOCK); -// try -// { -// byte[] requestBarr = serialize(info); -// return performRequest(requestBarr); -// } -// catch(Throwable t) -// { -// throw new LockRuntimeException("Cannot remove read lock for '" -// + resourceId + "' using key '" + key + "'", t); -// } -// } - public void releaseLocks(Object key) { LockInfo info = new LockInfo(key, null, METHOD_RELEASE_LOCKS); @@ -290,25 +267,6 @@ } } - private HttpURLConnection getHttpUrlConnection() - throws MalformedURLException, IOException, ProtocolException - { - URL lockserver = getLockserverUrl(); - HttpURLConnection conn = (HttpURLConnection) lockserver.openConnection(); - - conn.setDoInput(true); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - conn.setAllowUserInteraction(false); - conn.setUseCaches(false); - return conn; - } - - private URL getLockserverUrl() - { - return lockservlet; - } - public byte[] serialize(Object obj) throws IOException { ByteArrayOutputStream bao = new ByteArrayOutputStream(); @@ -316,8 +274,7 @@ oos.writeObject(obj); oos.close(); bao.close(); - byte[] result = bao.toByteArray(); - return result; + return bao.toByteArray(); } private boolean performRequest(byte[] requestBarr) throws IOException, ClassNotFoundException @@ -329,7 +286,7 @@ } else { - throw new LockRuntimeException("Remote lock server error, expect return value of type 'Boolean'"); + throw new LockRuntimeException("Remote lock server error, expect return value of type 'Boolean' but object was: " + result); } } @@ -342,7 +299,7 @@ } else { - throw new LockRuntimeException("Remote lock server error, expect return value of type 'String'"); + throw new LockRuntimeException("Remote lock server error, expect return value of type 'String' but object was: " + result); } } @@ -355,29 +312,66 @@ } else { - throw new LockRuntimeException("Remote lock server error, expect return value of type 'String'"); + throw new LockRuntimeException("Remote lock server error, expect return value of type 'Long' but object was: " + result); } } private Object performRequestObject(byte[] requestBarr) throws IOException, ClassNotFoundException { HttpURLConnection conn = getHttpUrlConnection(); + Object result = null; + try + { + conn.connect(); - //post request - BufferedOutputStream out = new BufferedOutputStream(conn.getOutputStream()); - out.write(requestBarr, 0, requestBarr.length); - out.flush(); - - // read result from - InputStream in = conn.getInputStream(); - ObjectInputStream ois = new ObjectInputStream(in); - Object result = ois.readObject(); - - // cleanup - ois.close(); - out.close(); - conn.disconnect(); + //post request + BufferedOutputStream out = new BufferedOutputStream(conn.getOutputStream()); + out.write(requestBarr, 0, requestBarr.length); + out.flush(); + + // read result from + InputStream in = conn.getInputStream(); + ObjectInputStream ois = new ObjectInputStream(in); + result = ois.readObject(); + // cleanup + ois.close(); + out.close(); + } + catch(IOException e) + { + e.printStackTrace(); + InputStream errStream = conn.getErrorStream(); + if(errStream != null) + { + BufferedReader err = new BufferedReader(new InputStreamReader(conn.getErrorStream())); + String errLine; + StringBuffer buf = new StringBuffer(); + while((errLine = err.readLine()) != null) + { + buf.append(SystemUtils.LINE_SEPARATOR).append(errLine); + } + log.error("Remote Error:" + buf.toString()); + } + throw e; + } + catch(RuntimeException e) + { + e.printStackTrace(); + throw e; + } + finally + { + try + { + if(conn != null) conn.disconnect(); + } + catch(Exception ignore) + { + // ignore + } + } + conn.disconnect(); if(result instanceof Throwable) { throw new LockRuntimeException("Remote lock server error", (Throwable) result); @@ -388,14 +382,24 @@ } } + private HttpURLConnection getHttpUrlConnection() + throws MalformedURLException, IOException, ProtocolException + { + HttpURLConnection connection = (HttpURLConnection) lockservlet.openConnection(); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setRequestMethod("PUT"); + connection.setAllowUserInteraction(false); + connection.setUseCaches(false); + return connection; + } + public static final class LockInfo implements Serializable { - public Object key; - public Object resourceId; + public String key; + public String resourceId; public int isolationLevel; public byte methodName; - public long lockTimeout; - public long blockTimeout; public LockInfo(byte methodName) { @@ -404,30 +408,17 @@ public LockInfo(Object key, Object resourceId, byte methodName) { - this.key = key; - this.resourceId = resourceId; + this.key = key != null ? key.toString() : null; + this.resourceId = resourceId != null ? resourceId.toString() : null; this.methodName = methodName; } public LockInfo(Object key, Object resourceId, int isolationLevel, byte methodName) { - this.key = key; - this.resourceId = resourceId; + this.key = key != null ? key.toString() : null; + this.resourceId = resourceId != null ? resourceId.toString() : null; this.isolationLevel = isolationLevel; this.methodName = methodName; } - -// public LockInfo(long timeout, byte methodName) -// { -// if(methodName == METHOD_LOCK_TIMEOUT_SET) -// { -// this.lockTimeout = timeout; -// } -// else -// { -// this.blockTimeout = timeout; -// } -// this.methodName = methodName; -// } } } Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerServlet.java URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerServlet.java?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerServlet.java (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/locking/LockManagerServlet.java Sat Jan 28 03:05:34 2006 @@ -16,8 +16,8 @@ */ -import javax.servlet.ServletException; import javax.servlet.ServletConfig; +import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -26,13 +26,20 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Date; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.ojb.broker.util.ClassHelper; /** - * @author Thomas Mahler + * OJB's locking server servlet used to perform distributed lock requests from different + * nodes - internal this class use a {@link LockManagerInMemoryImpl} instance + * to manage the lock objects. + * + * @version $Id: $ */ public class LockManagerServlet extends HttpServlet { @@ -40,6 +47,7 @@ static final String STR_LOCK_TIMEOUT = "lockTimeout"; static final String STR_BLOCK_TIMEOUT = "blockTimeout"; static final String STR_LOCK_MANAGER = "lockManager"; + private static final String prefix = "[ojb-lockserver] "; private static long numRequests; private static Throwable lastError = null; @@ -47,20 +55,24 @@ public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); + // if lock manager was instantiated not yet if(lockmanager == null) { lastError = null; numRequests = 0; + System.out.println(prefix + "Start ojb-locking servlet"); String strLockManager = servletConfig.getInitParameter(STR_LOCK_MANAGER); try { lockmanager = (LockManager) (strLockManager != null ? ClassHelper.newInstance(strLockManager) : ClassHelper.newInstance(LockManagerInMemoryImpl.class)); + System.out.println(prefix + "Used LockManager: " + lockmanager.getClass()); } catch(Exception e) { - lastError = new LockRuntimeException("Can't instance lock manager, init parameter 'lockManager': " + strLockManager); + lastError = new LockRuntimeException( + "Can't instance lock manager, init parameter '" + STR_LOCK_MANAGER + "': " + strLockManager); e.printStackTrace(); } String strTimeout = servletConfig.getInitParameter(STR_LOCK_TIMEOUT); @@ -70,12 +82,14 @@ { Long lockTimeout = NumberUtils.createLong(strTimeout); lockmanager.setLockTimeout(lockTimeout.longValue()); + System.out.println(prefix + "Set lock-timeout=" + lockTimeout); } catch(Exception e) { if(lastError == null) { - lastError = new LockRuntimeException("Can't convert 'lockTimeout' init parameter: " + strTimeout); + lastError = new LockRuntimeException( + "Can't convert init parameter '" + STR_LOCK_TIMEOUT + "': " + strTimeout); } e.printStackTrace(); } @@ -86,7 +100,8 @@ try { Long blockTimeout = NumberUtils.createLong(strBlock); - lockmanager.setLockTimeout(blockTimeout.longValue()); + lockmanager.setBlockTimeout(blockTimeout.longValue()); + System.out.println(prefix + "Set block-timeout=" + blockTimeout); } catch(Exception e) { @@ -113,23 +128,35 @@ out.println("OJB Distributed Locking Servlet Status Page"); out.println("

OJB Distributed Locking Servlet

"); - out.println("The servlet is running.

"); if(lastError == null) { - out.println("The LockServer is running.

"); - out.println("LockManager info: " + lockmanager.getLockInfo() + "

"); - out.println("Processed Lock Request: " + numRequests + "

"); + out.println("The LockManager is running (" + new Date().toString() +")

"); + out.println("LockManager info:

" + lockmanager.getLockInfo() + "

"); + out.println("Processed Lock Request: " + numRequests + "

"); } else { out.println("

The LockServer has a problem!

"); - out.println("The error message is:

"); - out.println(lastError.getMessage() + "

"); + out.println("The error message is:

"); + out.println(lastError.getMessage() + "

"); lastError.printStackTrace(out); lastError = null; } + out.println("

Servlet Information

"); + out.println(""); + Enumeration names = request.getHeaderNames(); + while(names.hasMoreElements()) + { + String name = (String) names.nextElement(); + out.println(""); + out.println(" "); + out.println(" "); + out.println(""); + } + out.println("
" + name + ":" + request.getHeader(name) + "
"); + out.println(""); } @@ -139,6 +166,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doPut(request, response); + } + + protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + //response.setContentType("image/x-pixmap"); + response.setContentType("application/xml"); + //response.setContentType("text/html"); + response.setHeader("pragma", "no-cache"); // update counter numRequests++; @@ -146,88 +182,78 @@ { // read request: LockManagerRemoteImpl.LockInfo info = (LockManagerRemoteImpl.LockInfo) buildObjectFromRequest(request); - Object result = null; + Object result; // now execute the command specified by the selector try { switch(info.methodName) { case LockManagerRemoteImpl.METHOD_READ_LOCK: - { - result = new Boolean(lockmanager.readLock(info.key, info.resourceId, info.isolationLevel)); - break; - } + { + result = BooleanUtils.toBooleanObject(lockmanager.readLock(info.key, info.resourceId, info.isolationLevel)); + break; + } case LockManagerRemoteImpl.METHOD_RELEASE_SINGLE_LOCK: - { - result = new Boolean(lockmanager.releaseLock(info.key, info.resourceId)); - break; - } + { + result = BooleanUtils.toBooleanObject(lockmanager.releaseLock(info.key, info.resourceId)); + break; + } case LockManagerRemoteImpl.METHOD_RELEASE_LOCKS: - { - lockmanager.releaseLocks(info.key); - result = Boolean.TRUE; - break; - } + { + lockmanager.releaseLocks(info.key); + result = Boolean.TRUE; + break; + } case LockManagerRemoteImpl.METHOD_WRITE_LOCK: - { - result = new Boolean(lockmanager.writeLock(info.key, info.resourceId, - info.isolationLevel)); - break; - } + { + result = BooleanUtils.toBooleanObject(lockmanager.writeLock(info.key, info.resourceId, + info.isolationLevel)); + break; + } case LockManagerRemoteImpl.METHOD_UPGRADE_LOCK: - { - result = new Boolean(lockmanager.upgradeLock(info.key, info.resourceId, info.isolationLevel)); - break; - } + { + result = BooleanUtils.toBooleanObject(lockmanager.upgradeLock(info.key, info.resourceId, info.isolationLevel)); + break; + } case LockManagerRemoteImpl.METHOD_CHECK_READ: - { - result = new Boolean(lockmanager.hasRead(info.key, info.resourceId)); - break; - } + { + result = BooleanUtils.toBooleanObject(lockmanager.hasRead(info.key, info.resourceId)); + break; + } case LockManagerRemoteImpl.METHOD_CHECK_WRITE: - { - result = new Boolean(lockmanager.hasWrite(info.key, info.resourceId)); - break; - } + { + result = BooleanUtils.toBooleanObject(lockmanager.hasWrite(info.key, info.resourceId)); + break; + } case LockManagerRemoteImpl.METHOD_CHECK_UPGRADE: - { - result = new Boolean(lockmanager.hasUpgrade(info.key, info.resourceId)); - break; - } + { + result = BooleanUtils.toBooleanObject(lockmanager.hasUpgrade(info.key, info.resourceId)); + break; + } case LockManagerRemoteImpl.METHOD_LOCK_INFO: - { - result = lockmanager.getLockInfo(); - break; - } + { + result = lockmanager.getLockInfo(); + break; + } case LockManagerRemoteImpl.METHOD_LOCK_TIMEOUT: - { - result = new Long(lockmanager.getLockTimeout()); - break; - } + { + result = new Long(lockmanager.getLockTimeout()); + break; + } case LockManagerRemoteImpl.METHOD_BLOCK_TIMEOUT: - { - result = new Long(lockmanager.getBlockTimeout()); - break; - } -// case LockManagerRemoteImpl.METHOD_LOCK_TIMEOUT_SET: -// { -// lockmanager.setLockTimeout(info.lockTimeout); -// break; -// } -// -// case LockManagerRemoteImpl.METHOD_BLOCK_TIMEOUT_SET: -// { -// lockmanager.setBlockTimeout(info.blockTimeout); -// break; -// } + { + result = new Long(lockmanager.getBlockTimeout()); + break; + } default : - { - throw new LockRuntimeException("Unknown command:" + info.methodName); - } + { + throw new LockRuntimeException("Unknown command:" + info.methodName); + } } } catch(RuntimeException e) { + e.printStackTrace(); result = new LockRuntimeException("Error while invoke specified method in servlet.", e); } @@ -243,13 +269,12 @@ } } - private Object buildObjectFromRequest(HttpServletRequest request) throws IOException, ClassNotFoundException + private Object buildObjectFromRequest(final HttpServletRequest request) throws IOException, ClassNotFoundException { - Object obj = null; // get the body of the request as binary data InputStream is = request.getInputStream(); ObjectInputStream objInputStream = new ObjectInputStream(is); - obj = objInputStream.readObject(); + Object obj = objInputStream.readObject(); objInputStream.close(); is.close(); return obj; Modified: db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/web.xml URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/web.xml?rev=373136&r1=373135&r2=373136&view=diff ============================================================================== --- db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/web.xml (original) +++ db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/web.xml Sat Jan 28 03:05:34 2006 @@ -15,15 +15,14 @@ * limitations under the License. */ --> - + - - - OJB ODMG Lock Server + OJB Lock-Server - OJB ODMG Lock Server + The OJB locking server servlet @@ -35,7 +34,8 @@ lockTimeout - 80000 + + 600000 blockTimeout --------------------------------------------------------------------- To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org For additional commands, e-mail: ojb-dev-help@db.apache.org