db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
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 GMT
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.
+     * <br/>
      * All so called <em>non-blocking</em> 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 <a href="mailto:arminw@apache.org">Armin Waibel</a>
  * @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("<html><head><title>OJB Distributed Locking Servlet Status Page</title>");
         out.println("</head><body><h1>OJB Distributed Locking Servlet</h1>");
-        out.println("The servlet is running.<p>");
 
         if(lastError == null)
         {
-            out.println("The LockServer is running.<p>");
-            out.println("LockManager info: " + lockmanager.getLockInfo() + "<p>");
-            out.println("Processed Lock Request: " + numRequests + "<p>");
+            out.println("<strong>The LockManager is running </strong>(" + new Date().toString() +")<p/>");
+            out.println("<strong>LockManager info:</strong><pre>" + lockmanager.getLockInfo() + "</pre><p/>");
+            out.println("<strong>Processed Lock Request: </strong>" + numRequests + "<p/>");
         }
         else
         {
             out.println("<h2>The LockServer has a problem!</h2>");
-            out.println("The error message is:<p>");
-            out.println(lastError.getMessage() + "<p>");
+            out.println("The error message is:<p/>");
+            out.println(lastError.getMessage() + "<p/>");
             lastError.printStackTrace(out);
             lastError = null;
         }
 
+        out.println("<h3>Servlet Information</h3>");
+        out.println("<table border=\"0\" width=\"100%\">");
+        Enumeration names = request.getHeaderNames();
+        while(names.hasMoreElements())
+        {
+            String name = (String) names.nextElement();
+            out.println("<tr>");
+            out.println("  <th align=\"right\">" + name + ":</th>");
+            out.println("  <td>" + request.getHeader(name) + "</td>");
+            out.println("</tr>");
+        }
+        out.println("</table>");
+
         out.println("</body></html>");
     }
 
@@ -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.
  */
 -->
-<!DOCTYPE web-app
-    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
-    "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+    version="2.4">
 
-<web-app>
-
-    <display-name>OJB ODMG Lock Server</display-name>
+    <display-name>OJB Lock-Server</display-name>
     <description>
-     OJB ODMG Lock Server
+     The OJB locking server servlet
     </description>
 
     <servlet>
@@ -35,7 +34,8 @@
         </init-param>
         <init-param>
             <param-name>lockTimeout</param-name>
-            <param-value>80000</param-value>
+            <!-- set lock timeout to 10 minutes (setting in [ms]) -->
+            <param-value>600000</param-value>
         </init-param>
         <init-param>
             <param-name>blockTimeout</param-name>



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message