Package org.xmlBlaster.test.classtest.queue

Source Code of org.xmlBlaster.test.classtest.queue.JdbcQueueTest$ConnectionConsumer

package org.xmlBlaster.test.classtest.queue;

import java.sql.Connection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.xmlBlaster.util.Global;
import org.xmlBlaster.util.StopWatch;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.def.Constants;
import org.xmlBlaster.util.def.ErrorCode;
import org.xmlBlaster.util.def.PriorityEnum;
import org.xmlBlaster.util.plugin.PluginInfo;
import org.xmlBlaster.util.qos.storage.CbQueueProperty;
import org.xmlBlaster.util.qos.storage.QueuePropertyBase;
import org.xmlBlaster.util.queue.I_Entry;
import org.xmlBlaster.util.queue.I_Queue;
import org.xmlBlaster.util.queue.QueuePluginManager;
import org.xmlBlaster.util.queue.StorageId;
import org.xmlBlaster.util.queue.jdbc.JdbcConnectionPool;
import org.xmlBlaster.util.queuemsg.DummyEntry;

/**
* Test JdbcQueuePlugin failover when persistent store disappears.
* <p>
* Invoke: java org.xmlBlaster.test.classtest.queue.JdbcQueueTest
* </p>
* <p>
* Test database with PostgreSQL:
* </p>
* <pre>
* initdb /tmp/postgres
* cp /var/lib/pgsql/data/pg_hba.conf /tmp/postgres    (edit host access)
* createdb test
* postmaster -i -D /tmp/postgres
* </pre>
* @see org.xmlBlaster.util.queue.I_Queue
* @see org.xmlBlaster.util.queue.jdbc.JdbcQueuePlugin
*/
public class JdbcQueueTest extends TestCase {
  
  
   public class ConnectionConsumer extends Thread {
      private JdbcConnectionPool pool;
      private int count;
     
      public ConnectionConsumer(JdbcConnectionPool pool, int count) {
         this.pool = pool;
         this.count = count;
         start();
      }
     
      public void run() {
         boolean success = true;
         try {
            log.info("connectionConsumer " + this.count + " starting");
            Connection conn = this.pool.getConnection();
            log.info("connectionConsumer " + this.count + " got the connection " + conn);
            if (conn != null)
               this.pool.releaseConnection(conn, success);
         }
         catch (XmlBlasterException ex) {
            log.info("connectionConsumer exception " + ex.getMessage());
            if (ex.getErrorCode().getErrorCode().equals(ErrorCode.RESOURCE_TOO_MANY_THREADS.getErrorCode())) {
               synchronized(JdbcQueueTest.class) {
                  exceptionCount++;
               }
            }
         }
      }
     
   }
  
   int exceptionCount = 0;
  
   private String ME = "JdbcQueueTest";
   protected Global glob;
   private static Logger log = Logger.getLogger(JdbcQueueTest.class.getName());
   private long sizeOfMsg  = 100L;
   private I_Queue queue   = null;

   public List<I_Entry> queueList = null;
//   public static String[] PLUGIN_TYPES = { new String("JDBC"), new String("CACHE") };
   public static String[] PLUGIN_TYPES = { new String("JDBC") };
   public int count = 0;
   boolean suppressTest = false;
   boolean doExecute = true;

   /** Constructor for junit not possible since we need to run it 3 times
   public JdbcQueueTest(String name) {
      super(name);
      for (int i=0; i < NUM_IMPL; i++)
         initialize(new Global(), name, i);
   }
   */

   public JdbcQueueTest(Global glob, String name, int currImpl, boolean doExecute) {
      super(name);
      this.doExecute = doExecute;
      initialize(glob, name, currImpl);
   }

   private void initialize(Global glob, String name, int currImpl) {
      this.glob = Global.instance();


      this.sizeOfMsg = glob.getProperty().get("sizes", 10L);
      this.suppressTest = false;
      this.count = currImpl;

      try {
         String type = PLUGIN_TYPES[currImpl];
         this.glob.getProperty().set("cb.queue.persistent.tableNamePrefix", "TEST");
         QueuePluginManager pluginManager = new QueuePluginManager(glob);
         PluginInfo pluginInfo = new PluginInfo(glob, pluginManager, type, "1.0");
         java.util.Properties prop = (java.util.Properties)pluginInfo.getParameters();
         prop.put("tableNamePrefix", "TEST");
         prop.put("entriesTableName", "_entries");

         CbQueueProperty cbProp = new CbQueueProperty(glob, Constants.RELATING_CALLBACK, "/node/test");
         StorageId queueId = new StorageId(glob, Constants.RELATING_CALLBACK, "SetupQueue");

         this.queue = pluginManager.getPlugin(pluginInfo, queueId, cbProp);
         this.queue.shutdown(); // to allow to initialize again
      }
      catch (Exception ex) {
         log.severe("setUp: error when setting the property 'cb.queue.persistent.tableNamePrefix' to 'TEST'");
      }
   }

   protected void setUp() {

      try {
         glob.getProperty().set("cb.queue.persistent.tableNamePrefix", "TEST");
         ME = "JdbcQueueTest with class: " + PLUGIN_TYPES[this.count];
      }
      catch (Exception ex) {
         log.severe("setUp: error when setting the property 'cb.queue.persistent.tableNamePrefix' to 'TEST'" + ex.getMessage());
      }

      // cleaning up the database from previous runs ...

      try {
         // test initialize()
//         this.queue.destroy();
         this.queue.shutdown();
      }
      catch (Exception ex) {
         log.severe("could not propertly set up the database: " + ex.getMessage());
         this.suppressTest = true;
      }
   }

   public void tearDown() {
      try {
         this.queue.clear();
         this.queue.shutdown();
      }
      catch (Exception ex) {
         log.warning("error when tearing down " + ex.getMessage() + " this normally happens when invoquing multiple times cleanUp " + ex.getMessage());
      }
   }

  
   public void testPutWithBreak() {
      if (this.suppressTest) {
         log.severe("JDBC test is not driven as no database was found");
         return;
      }
      try {
         if (this.doExecute) putWithBreak();
         else {
            log.warning("test desactivated since needs to be run manually");
            log.warning("please invoke it as 'java org.xmlBlaster.test.classtest.queue.JdbcQueueTest'");
         }
      }
      catch (XmlBlasterException ex) {
         fail("Exception when testing PutWithBreak probably due to failed initialization of the queue of type " + PLUGIN_TYPES[this.count] + " " + ex.getMessage() );
         ex.printStackTrace();
      }
   }

   public void putWithBreak() throws XmlBlasterException {
      String me = ME + ".putWithBreak";
      // set up the queues ....
      QueuePropertyBase prop = new CbQueueProperty(glob, Constants.RELATING_CALLBACK, "/node/test");
      prop.setMaxEntries(10000);
      StorageId queueId = new StorageId(glob, Constants.RELATING_CALLBACK, "putWithBreak");
      queue.initialize(queueId, prop);
      queue.clear();

      int num = 30;
      boolean success = false;
      for (int i=0; i < num; i++) {
         try {
            log.info("put with break entry " + i + "/" + num + " please kill the DB manually to test reconnect");
            DummyEntry entry = new DummyEntry(glob, PriorityEnum.NORM_PRIORITY, queue.getStorageId(), sizeOfMsg, true);
            queue.put(entry, false);
            try {
               Thread.sleep(5000L);
            }
            catch (Exception ex) {
            }
         }
         catch (XmlBlasterException ex) {
            if (log.isLoggable(Level.FINE))  log.fine(ex.getMessage());
            if ("resource.db.unavailable".equalsIgnoreCase(ex.getErrorCodeStr())) {
               log.info("the communication to the db has been lost");
               success = true;
               break;
            }
            else throw ex;
         }
      }
     
      assertTrue(me + ": Timed out when waiting to loose the connection to the DB", success);
      success = false; // reset the flag
      log.info("preparing to reconnect again ...");

      for (int i=0; i < num; i++) {
         try {
            log.info("put with break entry " + i + "/" + num + " please restart the the DB to test reconnect");
            DummyEntry entry = new DummyEntry(glob, PriorityEnum.NORM_PRIORITY, queue.getStorageId(), sizeOfMsg, true);
            queue.put(entry, false);
            log.info("the communication to the db has been reestablished");
            success = true;
            break;
         }
         catch (XmlBlasterException ex) {
            if (log.isLoggable(Level.FINE))  log.fine(ex.getMessage());
            if ("resource.db.unavailable".equalsIgnoreCase(ex.getErrorCodeStr())) {
               try {
                  Thread.sleep(5000L);
               }
               catch (Exception e) {
               }
            }
            else throw ex;
         }
      }
      assertTrue(me + ": Timed out when waiting to regain the connection to the DB", success);
      log.info("successfully ended");
   }

   public void testInitialEntries() {
      if (this.suppressTest) {
         log.severe("JDBC test is not driven as no database was found");
         return;
      }
      try {
         initialEntries();
      }
      catch (XmlBlasterException ex) {
         fail("Exception when testing InitialEntries probably due to failed initialization of the queue of type " + PLUGIN_TYPES[this.count] + " " + ex.getMessage() );
         ex.printStackTrace();
      }
   }

   public void initialEntries() throws XmlBlasterException {
      // set up the queues ....
      log.info("initialEntries test starts");
      QueuePropertyBase cbProp = new CbQueueProperty(glob, Constants.RELATING_CALLBACK, "/node/test");
      cbProp.setMaxEntries(10000L);
      cbProp.setMaxBytes(200000L);
      StorageId queueId = new StorageId(glob, Constants.RELATING_CALLBACK, "initialEntries");

      try {
         String type = PLUGIN_TYPES[this.count];
         this.glob.getProperty().set("cb.queue.persistent.tableNamePrefix", "TEST");
         QueuePluginManager pluginManager = new QueuePluginManager(glob);
         PluginInfo pluginInfo = new PluginInfo(glob, pluginManager, type, "1.0");
         java.util.Properties prop = (java.util.Properties)pluginInfo.getParameters();
         prop.put("tableNamePrefix", "TEST");
         prop.put("entriesTableName", "_entries");
         I_Queue tmpQueue = pluginManager.getPlugin(pluginInfo, queueId, cbProp);
         tmpQueue.clear();
         // add some persistent entries and then shutdown ...
         DummyEntry entry = new DummyEntry(glob, PriorityEnum.NORM_PRIORITY, queue.getStorageId(), 100, true);
         tmpQueue.put(entry, false);
         entry = new DummyEntry(glob, PriorityEnum.NORM_PRIORITY, queue.getStorageId(), 100, true);
         tmpQueue.put(entry, false);
         entry = new DummyEntry(glob, PriorityEnum.NORM_PRIORITY, queue.getStorageId(), 100, true);
         tmpQueue.put(entry, false);
         tmpQueue.shutdown(); // to allow to initialize again
         I_Queue tmpQueue2 = pluginManager.getPlugin(pluginInfo, queueId, cbProp);
         long numOfEntries = tmpQueue2.getNumOfEntries();
         assertEquals("Wrong number of entries in queue", 3L, numOfEntries);
         List<I_Entry> lst = tmpQueue2.peek(-1, -1L);
         assertEquals("Wrong number of entries retrieved from queue", 3, lst.size());
         queue.shutdown();
      }
      catch (Exception ex) {
         log.severe("setUp: error when setting the property 'cb.queue.persistent.tableNamePrefix' to 'TEST'");
         ex.printStackTrace();
         assertTrue("exception occured when testing initialEntries", false);
      }
      log.info("initialEntries test successfully ended");
   }




   public void testMultiplePut() {
      try {
         multiplePut();
      }
      catch (XmlBlasterException ex) {
         fail("Exception when testing multiplePut probably due to failed initialization of the queue of type " + PLUGIN_TYPES[this.count] + " " + ex.getMessage() );
         ex.printStackTrace();
      }
   }

   public void multiplePut() throws XmlBlasterException {
      // set up the queues ....
      log.info("initialEntries test starts");
      QueuePropertyBase cbProp = new CbQueueProperty(glob, Constants.RELATING_CALLBACK, "/node/test");
      cbProp.setMaxEntries(10000L);
      cbProp.setMaxBytes(200000L);
      StorageId queueId = new StorageId(glob, Constants.RELATING_CALLBACK, "initialEntries");

      try {
         String type = PLUGIN_TYPES[this.count];
         this.glob.getProperty().set("cb.queue.persistent.tableNamePrefix", "TEST");
         QueuePluginManager pluginManager = new QueuePluginManager(glob);
         PluginInfo pluginInfo = new PluginInfo(glob, pluginManager, type, "1.0");
         java.util.Properties prop = (java.util.Properties)pluginInfo.getParameters();
         prop.put("tableNamePrefix", "TEST");
         prop.put("entriesTableName", "_entries");
         I_Queue tmpQueue = pluginManager.getPlugin(pluginInfo, queueId, cbProp);
         tmpQueue.clear();
         // add some persistent entries and then shutdown ...
         int nmax = 1;
         int size = 100;

         for (int j=0; j < 4; j++) {
            DummyEntry[] entries = new DummyEntry[nmax];
            for (int i=0; i < nmax; i++) {
               entries[i] = new DummyEntry(glob, PriorityEnum.NORM_PRIORITY, queue.getStorageId(), size, true);
            }
            long time1 = System.currentTimeMillis();
            tmpQueue.put(entries, false);
            long delta = System.currentTimeMillis() - time1;
            log.info("multiple put '" + nmax + "' entries took '" + 0.001 * delta + "' seconds which is '" + 1.0 * delta / nmax + "' ms per entry");
          
            List<I_Entry> list = tmpQueue.peek(-1, -1L);
            assertEquals("Wrong number of entries in queue", nmax, list.size());
          
            time1 = System.currentTimeMillis();
            tmpQueue.removeRandom(entries);
            delta = System.currentTimeMillis() - time1;
            log.info("multiple remove '" + nmax + "' entries took '" + 0.001 * delta + "' seconds which is '" + 1.0 * delta / nmax + "' ms per entry");
            tmpQueue.clear();
          
            time1 = System.currentTimeMillis();
            for (int i=0; i < nmax; i++) {
               tmpQueue.put(entries[i], false);
            }
            delta = System.currentTimeMillis() - time1;
            log.info("repeated single put '" + nmax + "' entries took '" + 0.001 * delta + "' seconds which is '" + 1.0 * delta / nmax + "' ms per entry");
          
            time1 = System.currentTimeMillis();
            for (int i=0; i < nmax; i++) tmpQueue.removeRandom(entries[i]);
            delta = System.currentTimeMillis() - time1;
            log.info("repeated single remove '" + nmax + "' entries took '" + 0.001 * delta + "' seconds which is '" + 1.0 * delta / nmax + "' ms per entry");
            nmax *= 10;
         }
         tmpQueue.shutdown(); // to allow to initialize again
      }
      catch (Exception ex) {
         log.severe("setUp: error when setting the property 'cb.queue.persistent.tableNamePrefix' to 'TEST'");
         ex.printStackTrace();
         assertTrue("exception occured when testing initialEntries", false);
      }
      log.info("initialEntries test successfully ended");
   }


   public void testConnectionPool() {
      try {
         log.info(" starting ");
         int numConn = 3;
         int maxWaitingThreads = 10;

         Global ownGlobal = this.glob.getClone(null);

         QueuePluginManager pluginManager = new QueuePluginManager(ownGlobal);
         PluginInfo pluginInfo = new PluginInfo(ownGlobal, pluginManager, "JDBC", "1.0");

         pluginInfo.getParameters().put("connectionBusyTimeout", "10000");
         pluginInfo.getParameters().put("maxWaitingThreads", "" + maxWaitingThreads);
         pluginInfo.getParameters().put("connectionPoolSize", "" + numConn);

         JdbcConnectionPool pool = new JdbcConnectionPool();
         pool.initialize(ownGlobal, pluginInfo.getParameters());

         Connection[] conn = new Connection[numConn];        
         for (int i=0; i < numConn; i++) {
            log.info(" getting connection " + i);
            conn[i] = pool.getConnection();
            assertNotNull("The connection " + i + " shall not be null", conn[i]);
         }
        
         log.info(" getting extra connection");
        
         Connection extraConn = null;
         try {
            extraConn = pool.getConnection();
            assertTrue("An Exception should have occured here: ", false);
         }
         catch (Exception ex) {
         }
         // should wait 10 seconds and then return null
         assertNull("the extra connection should be null", extraConn);
         boolean success = true;
         pool.releaseConnection(conn[0], success);
         extraConn = pool.getConnection();
         assertNotNull("the extra connection should not be null", extraConn);
         //pool.releaseConnection(extraConn);

         this.exceptionCount = 0;        
         int expectedEx = 4;
         for (int i=0; i < maxWaitingThreads + expectedEx; i++) {
            ConnectionConsumer cc = new ConnectionConsumer(pool, i);
         }
         try {
            Thread.sleep(15000L);
         }
         catch (InterruptedException ex) {
         }
         assertEquals("Number of exceptions due to too many waiting threads is wrong", expectedEx, this.exceptionCount);
         log.info(" successfully ended ");
      }
      catch (Exception ex) {
         fail("Exception when testing multiplePut probably due to failed initialization of the queue of type " + PLUGIN_TYPES[this.count] + " " + ex.getMessage() );
         ex.printStackTrace();
      }
   }


   /**
    * Method is used by TestRunner to load these tests
    */
   public static Test suite() {
      TestSuite suite= new TestSuite();
      Global glob = new Global();
      for (int i=0; i < PLUGIN_TYPES.length; i++) {
         suite.addTest(new JdbcQueueTest(glob, "testConnectionPool", i, true));
         suite.addTest(new JdbcQueueTest(glob, "testMultiplePut", i, true));
         suite.addTest(new JdbcQueueTest(glob, "testPutWithBreak", i, false));
         suite.addTest(new JdbcQueueTest(glob, "testInitialEntries", i, true));
      }
      return suite;
   }

   /**
    * <pre>
    *  java org.xmlBlaster.test.classtest.queue.JdbcQueueTest
    * </pre>
    */
   public static void main(String args[]) {
      Global glob = new Global(args);

      for (int i=0; i < PLUGIN_TYPES.length; i++) {
         JdbcQueueTest testSub = new JdbcQueueTest(glob, "JdbcQueueTest", i, true);

         testSub.setUp();
         testSub.testConnectionPool();
         testSub.tearDown();

         testSub.setUp();
         testSub.testMultiplePut();
         testSub.tearDown();

         testSub.setUp();
         testSub.testPutWithBreak();
         testSub.tearDown();

         testSub.setUp();
         testSub.testInitialEntries();
         testSub.tearDown();
      }
   }
}
TOP

Related Classes of org.xmlBlaster.test.classtest.queue.JdbcQueueTest$ConnectionConsumer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.