Thanks to Norbert and Bela for the reply.

I tested Norberts theory on Thread start position, and it didn't seem to make 
any difference.

I took Bela's test case, and this test does work, BUT WITH ONE subtle 
difference.

In Bela's test case, he places a value in the cache before starting things.  

This is a _crucial_  difference to mine.  

If I commented out the initial put(..) call before the Readers are created and 
started, I get the same results as my original test case, Reader 2 actually 
reads the null while Reader 1 is pausing.

Here is example output from Bela's original test case:


  | main: sleeping for 100
  | reader1: about to access tree
  | reader1: accessed tree, retval: testvalue
  | reader1: sleeping for 3000
  | reader2: about to access tree
  | reader1: About to commit
  | reader1: committed, exiting
  | reader2: accessed tree, retval: testvalue
  | reader2: About to commit
  | reader2: committed, exiting

The above is exactly what I want, but also occuring when there is null values 
in the cache.  Here's the output when you simply comment out the first put(...) 
call:


  | main: sleeping for 100
  | reader1: about to access tree
  | reader1: accessed tree, retval: null
  | reader1: sleeping for 3000
  | reader2: about to access tree
  | reader2: accessed tree, retval: null
  | reader2: About to commit
  | reader2: committed, exiting
  | reader1: About to commit
  | reader1: committed, exiting

A null value in the cache seems to be specially treated, as it does not block 
reads.   Unfortunately I need serialized access (read or write) to each leaf 
node in the tree to guarantee that 2 threads don't try to go off and hit the db 
and potentially clobber each other.

Here is the complete test case that I adapted from Bela's original, combining 
it with the basic shell provided by the 
org.jboss.test.cache.perf.basic.LocalPerfTestCase class that is provided in the 
examples src of the distro.  You will note that I have added the code to set 
the cache Isolation level in the initCache() method:


package com.aconex.jbosscache;
  | 
  | import java.util.Properties;
  | 
  | import javax.naming.Context;
  | import javax.naming.InitialContext;
  | import javax.transaction.UserTransaction;
  | 
  | import org.jboss.cache.PropertyConfigurator;
  | import org.jboss.cache.TreeCache;
  | import org.jboss.cache.lock.IsolationLevel;
  | import org.jboss.cache.transaction.DummyTransactionManager;
  | 
  | import junit.framework.TestCase;
  | 
  | /**
  |  * @author psmith
  |  *  
  |  */
  | public class SerializableTests extends TestCase {
  |     TreeCache cache_;
  | 
  |     int cachingMode_ = TreeCache.LOCAL;
  | 
  |     final static Properties p_;
  | 
  |     //     final static Logger log_ = 
Logger.getLogger(LocalPerfAopTest.class);
  |     String oldFactory_ = null;
  | 
  |     final String FACTORY = 
"org.jboss.cache.transaction.DummyContextFactory";
  | 
  |     DummyTransactionManager tm_;
  | 
  |     static {
  |             p_ = new Properties();
  |             p_.put(Context.INITIAL_CONTEXT_FACTORY,
  |                             
"org.jboss.cache.transaction.DummyContextFactory");
  |     }
  | 
  |     /*
  |      * @see TestCase#setUp()
  |      */
  |     protected void setUp() throws Exception {
  |             super.setUp();
  | 
  |             oldFactory_ = 
System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
  |             System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
  | 
  |             DummyTransactionManager.getInstance();
  |             initCaches(TreeCache.LOCAL);
  |             tm_ = new DummyTransactionManager();
  | 
  |             log("LocalPerfAopTest: cacheMode=LOCAL, one cache");
  |     }
  | 
  |     /**
  |      * @param string
  |      */
  |     private void log(String msg) {
  |             System.out.println(Thread.currentThread().getName() + ": " + 
msg);
  | 
  |     }
  | 
  |     /*
  |      * @see TestCase#tearDown()
  |      */
  |     protected void tearDown() throws Exception {
  |             super.tearDown();
  | 
  |             DummyTransactionManager.destroy();
  |             destroyCaches();
  | 
  |             if (oldFactory_ != null) {
  |                     System.setProperty(Context.INITIAL_CONTEXT_FACTORY, 
oldFactory_);
  |                     oldFactory_ = null;
  |             }
  |     }
  | 
  |     void initCaches(int caching_mode) throws Exception {
  |             cachingMode_ = caching_mode;
  |             cache_ = new TreeCache();
  |             PropertyConfigurator config = new PropertyConfigurator();
  |             config.configure(cache_, "META-INF/local-service.xml"); // read 
in
  |             // generic local
  |             // xml
  |             cache_
  |                             
.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
  |             cache_.setIsolationLevel(IsolationLevel.SERIALIZABLE);
  |             cache_.startService();
  |     }
  | 
  |     void destroyCaches() throws Exception {
  |             cache_.stopService();
  |             cache_ = null;
  |     }
  | 
  |     public void 
testConcurrentReadsWithSerializableIsolationLevelValueAlreadyInCache()
  |                     throws Exception {
  | 
  |             cache_.put("/testfqn", "testkey", "testvalue"); // add initial 
value, to
  |             runSerializableTest();
  |     }
  | 
  |     public void 
testConcurrentReadsWithSerializableIsolationLevelNOValueInCache()
  |                     throws Exception {
  | 
  |             runSerializableTest();
  |     }
  | 
  |     /**
  |      * @throws Exception
  |      * @throws InterruptedException
  |      */
  |     private void runSerializableTest() throws Exception, 
InterruptedException {
  |             final long TIMEOUT = 5000;
  |             Reader r1, r2;
  |             r1 = new Reader("reader1", 3000);
  |             r2 = new Reader("reader2", 0);
  |             r1.start();
  |             pause(100); // make sure thread1 starts and acquires the lock 
before
  |             // thread2
  |             r2.start();
  |             r1.join(TIMEOUT);
  |             r2.join(TIMEOUT);
  |     }
  | 
  |     /**
  |      * @param i
  |      * @throws Exception
  |      */
  |     private void pause(long i) throws Exception {
  |             log("sleeping for " + i);
  |             Thread.sleep(i);
  |     }
  | 
  |     class Reader extends Thread {
  |             long timeout;
  | 
  |             public Reader(String name, long timeout) {
  |                     super(name);
  |                     this.timeout = timeout;
  |             }
  | 
  |             public void run() {
  |                     UserTransaction trans = null;
  |                     try {
  |                             trans = (UserTransaction) new InitialContext(p_)
  |                                             .lookup("UserTransaction");
  |                             trans.begin();
  |                             Object retval = null;
  |                             log("about to access tree");
  |                             retval = cache_.get("testfqn", "testkey");
  |                             log("accessed tree, retval: " + retval);
  |                             if (timeout > 0) {
  |                                     pause(timeout);
  |                             }
  |                     } catch (Exception e) {
  |                             e.printStackTrace();
  |                     } finally {
  |                             log("About to commit");
  |                             try {
  |                                     trans.commit();
  |                             } catch (Throwable t) {
  |                             }
  |                             log("committed, exiting");
  |                     }
  |             }
  |     }
  | 
  | }

I would appreciate any thoughts on this.

cheers,

Paul Smith

View the original post : 
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3854886#3854886

Reply to the post : 
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=3854886


-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE
LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
_______________________________________________
JBoss-Development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to