Martin Kalén wrote:
Most important is: exactly which test runner
code are you using at the moment and exactly what are the semantics you
are trying to test

Attached you will find a slight modification of your original code that
will run two loops:
1. 500 store-ops in sequence
2. 500 store-ops spread over 20 parallell threads with 25 store-ops/thread

In part 1 you will always get 0 active brokers after each completed
store operation.

In part 2 you will get random results (completely unsynchronized,
asking for 20 parallell threads) with a maximum of 20 active brokers
at the end of each store operation.

(Completely independent on SequenceManager implementation used,
the difference in parallellism when using this unsynchronized pattern
is just a side-effect of different RDBMS roundtrip trimes/speed
between different implementations.)

At the end of part 2 you will always get 0 active brokers.

I hope this clarifies that the "leak" you saw is by design in your
test runner. The reason that you will almost always see as many active
brokers as you create thread is that it's very fast to create the
PersistenceBroker (increases active count), but takes time to connect
to DB and perform store op (=long time window of exposure before close
and decrease of active count). Number of active brokers is also not
related 1:1 to number of active Connection instances - this metric
is only available from the connection pool (and not readily available
in OJB 1.0.x, in OJB 1.1 there are monitoring calls for active/idle
connection cound from the pools).


Test conditions:
repository_database.xml
<jdbc-connection-descriptor jcd-alias="wang_lei" default-connection="false"
        username="ojb_test" password="ojb_test"
        dbalias="@127.0.0.1:1522:MARTIN"
        driver="oracle.jdbc.OracleDriver" jdbc-level="2.0"
        platform="Oracle" protocol="jdbc" subprotocol="oracle:thin"
        batch-mode="false" useAutoCommit="1">
  <object-cache class="org.apache.ojb.broker.cache.ObjectCachePerBrokerImpl"/>
  <connection-pool
        maxActive="20" maxIdle="10" whenExhaustedAction="2" maxWait="2000"
        validationQuery="SELECT 1 FROM DUAL"
        testOnBorrow="true" testOnReturn="false" testWhileIdle="false"/>
  <!-- different sequence managers tested -->
</jdbc-connection-descriptor>

OJB.properties
maxActive=20
maxIdle=10
maxWait=2000
timeBetweenEvictionRunsMillis=-1
whenExhaustedAction=2

Other settings are standard OJB v1.0.3 release properties.
The MyTest class and table DDL is according to your original post.

Regards,
 Martin
package se.curalia.test;

import junit.entity.MyTest;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerFactory;
import org.apache.ojb.broker.core.PersistenceBrokerFactoryFactory;

import java.util.ArrayList;
import java.util.List;

public class WangLei extends Thread
{

    private int storeOpsPerThread;
    private final PBKey key = new PBKey("wang_lei");

    public WangLei()
    {
        storeOpsPerThread = 1;
    }

    public WangLei(int storeOpsPerThread)
    {
        this.storeOpsPerThread = storeOpsPerThread;
    }

    public void run()
    {
        for (int i=0; i<storeOpsPerThread; i++) {
            doStoreNewInstance();
        }
    }

    private void doStoreNewInstance() {
        final String tId = Thread.currentThread().getName();

        MyTest t_Test = new MyTest();

        PersistenceBroker broker = null;
        try
        {
            broker = PersistenceBrokerFactory.createPersistenceBroker(key);

            broker.beginTransaction();
            broker.store(t_Test);
            broker.commitTransaction();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            if (broker != null) {
                try
                {
                    broker.abortTransaction();
                }
                catch (Exception e1)
                {
                    e1.printStackTrace();
                }
            }
        }
        finally
        {
            if (broker != null) {
                try
                {
                    broker.close();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }

        System.out.println("Id of stored class=" + t_Test.getTestId() +
                           ". Active brokers after storing instance in thread 
'" + tId + "': " +
                           
PersistenceBrokerFactoryFactory.instance().activePersistenceBroker());
    }

    public static void main(String[] args)
    {
        final int storeOps = 500;
        final int maxThreads = 20;

        System.out.println("----- Single-threaded, " + storeOps + " ops in 
sequence -----");
        for (int i=0; i<storeOps; i++) {
            WangLei wl = new WangLei();
            wl.doStoreNewInstance();
        }

        System.out.println("----- Multi-threaded, " + maxThreads + " threads in 
parallell -----");
        final List t_Threads = new ArrayList(maxThreads);
        for (int i=0; i<maxThreads; i++) {
            WangLei wl = new WangLei(storeOps / maxThreads);
            t_Threads.add(wl);
        }
        for (int i=0; i<maxThreads; i++) {
            Thread t_Thread = (Thread) t_Threads.get(i);
            t_Thread.start();
        }
    }

}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to