Package org.objectweb.speedo.runtime.concurrency

Source Code of org.objectweb.speedo.runtime.concurrency.TestManyUsers

/**
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package org.objectweb.speedo.runtime.concurrency;

import org.objectweb.speedo.AbstractSpeedo;
import org.objectweb.speedo.SpeedoTestHelper;
import org.objectweb.speedo.api.ExceptionHelper;
import org.objectweb.speedo.pobjects.userid.BasicB;
import org.objectweb.speedo.pobjects.basic.BasicA;
import org.objectweb.util.monolog.api.BasicLevel;

import javax.jdo.PersistenceManager;
import javax.jdo.JDOException;
import javax.jdo.JDOFatalException;
import javax.jdo.PersistenceManagerFactory;

import junit.framework.Assert;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.Iterator;

/**
* Tests the high concurrency of the Speedo (more than 100 users)
*
* @author S.Chassande-Barrioz
*/
public class TestManyUsers extends SpeedoTestHelper {

    public static final int W_ACTION = 1;
    public static final int R_W_ACTION = 2;
    public static final int MIXED_ACTION = 3;
   
  public static Vector rollbackExceptions = new Vector();
  public static Vector errors = new Vector();


  public TestManyUsers(String s) {
    super(s);
  }

  protected String getLoggerName() {
    return LOG_NAME + ".rt.concurrency.TestManyUsers";
  }

  /**
   * Tests the concurrency of the initialization of a class (mapping)
   * (1000 users)
   */
  public void testLoading() {
    final int nbThread = Integer.getInteger(
        "conform.org.objectweb.speedo.rt.concurrency.TestManyUsers.testLoading.thread",
        1000).intValue();
    logger.log(BasicLevel.INFO, "Run concurrent Loading, " + nbThread + " threads");
    Thread[] ts = new Thread[nbThread];
    for (int i = 0; i < nbThread; i++) {
      ts[i] = new Thread(
          new Runnable() {
            public void run() {
              try {
                PersistenceManager pm = pmf.getPersistenceManager();
                Thread.sleep(1);
                pm.getObjectIdClass(BasicB.class);
                pm.close();
                Assert.assertTrue(true);
              } catch (Exception e) {
                e.printStackTrace();
                fail(e.getMessage());
              }
            }
          }
      );
    }
    for (int i = 0; i < nbThread; i++) {
      ts[i].start();
    }
    try {
      for (int i = 0; i < nbThread; i++) {
        ts[i].join();
      }
    } catch (InterruptedException e) {
      fail(e.getMessage());
    }
  }

  /**
   * Tests the concurrency of several writer on a same persistent object.
   * (500 users). Action: a.writeF2(a.readF2() + 1)
   */
  public void testConcurrentReadAndWrite() {
    logger.log(BasicLevel.INFO, "");
    int nbThread = Integer.getInteger(
        "conform.org.objectweb.speedo.rt.concurrency.TestManyUsers.testConcurrentReadAndWrite.thread",
        200).intValue();
    logger.log(BasicLevel.INFO, "Run concurrent readAndWrite actions");
    int[] actions = new int[10];
    Arrays.fill(actions, R_W_ACTION);
    testAccess(nbThread, actions);
  }
  /**
   * Tests the concurrency of several writer on a same persistent object.
   * (500 users). Action = a.inc()
   */
  public void testConcurrentWrite() {
    logger.log(BasicLevel.INFO, "");
    int nbThread = Integer.getInteger(
        "conform.org.objectweb.speedo.rt.concurrency.TestManyUsers.testConcurrentWrite.thread",
        200).intValue();
    logger.log(BasicLevel.INFO, "Run concurrent write actions");
    int[] actions = new int[10];
    Arrays.fill(actions, W_ACTION);
    testAccess(nbThread, actions);
  }
  /**
   * Tests the concurrency of several writer on a same persistent object.
   * (500 users). Action = a.inc()
   */
  public void testConcurrentMixed() {
    logger.log(BasicLevel.INFO, "");
    int nbThread = Integer.getInteger(
        "conform.org.objectweb.speedo.rt.concurrency.TestManyUsers.testConcurrentWrite.thread",
        200).intValue();
    logger.log(BasicLevel.INFO, "Run concurrent mixed actions");
    int[] actions = new int[10];
    Arrays.fill(actions, MIXED_ACTION);
    testAccess(nbThread, actions);
  }
  /**
   * Tests the concurrency of several writer on a same persistent object.
   * (500 users)
   */
  public void testAccess(final int nbThread , final int[] actions) {
    final int initialValue = 0;
    rollbackExceptions.clear();
    errors.clear();
    Thread[] ts = new Thread[nbThread];
    BasicA ba = new BasicA();
    ba.writeF1("1");
    ba.writeF2(initialValue);
    PersistenceManager pm = pmf.getPersistenceManager();
    pm.currentTransaction().begin();
    pm.makePersistent(ba);
    final BasicA a = ba;
    Object id = pm.getObjectId(ba);
    pm.currentTransaction().commit();
    pm.close();
    for (int i = 0; i < nbThread; i++) {
      final int _i = i;
      ts[i] = new Thread(
          new Runnable() {
            public void run() {
                int action = (_i % 2 == 0 ? W_ACTION : R_W_ACTION);
                for(int j=0; j<actions.length; j++) {
              PersistenceManager pm = pmf.getPersistenceManager();
              boolean rollback = false;
              try {
                pm.currentTransaction().begin();
                logger.log(BasicLevel.DEBUG, _i + "," + j + " begin tx");
                switch(actions[j]) {
                case W_ACTION:
                  a.incF2();
                  break;
                case R_W_ACTION:
                  a.writeF2(a.readF2() + 1);
                  break;
                case MIXED_ACTION:
                    if (action == W_ACTION) {
                        a.incF2();
                        action = R_W_ACTION;
                    } else if (action == R_W_ACTION) {
                        a.writeF2(a.readF2() + 1);
                        action = W_ACTION;
                    }
                  break;
                }
                pm.currentTransaction().commit();
                logger.log(BasicLevel.DEBUG, _i + "," + j + " finished");
              } catch (JDOFatalException e) {
                rollback = true;
                rollbackExceptions.add(e);
                logger.log(BasicLevel.DEBUG, "Tx " + _i + "," + j + " has been rolledback");
              } catch (Exception e) {
                Exception ie = ExceptionHelper.getNested(e);
                errors.add(ie);
                logger.log(BasicLevel.ERROR, _i + "," + j + " has a problem", ie);
                pm.currentTransaction().rollback();
              } finally {
                try {
                  pm.close();
                } catch (JDOException e) {
                  logger.log(BasicLevel.ERROR, "tx " + _i
                          + "," + j + " has been "
                          + (rollback ? "rolledback" : "committed")
                          + " and the close occurs an error", ExceptionHelper.getNested(e));
                  throw e;
                }
              }               
              }
            }
          }
      );
    }
    long execTime = System.currentTimeMillis();     
    for (int i = 0; i < nbThread; i++) {
      ts[i].start();
    }
    int val = 0;
    ArrayList al = new ArrayList(nbThread);
    try {
      logger.log(BasicLevel.INFO, nbThread + " threads launched doing " + actions.length + " actions, waiting them ...");
      for (int i = 0; i < nbThread; i++) {
        ts[i].join(1000);
        if (ts[i].isAlive()) {
          al.add(new Integer(i));
          logger.log(BasicLevel.DEBUG, i + " is not finished after" +
                         " the delay, it could be blocked");
        }
      }
      String dg = getDG(pmf);
      if (dg != null) {
          logger.log(BasicLevel.INFO, dg);
      }
      if (al.size() > 0) {
        for (Iterator it = al.iterator(); it.hasNext();) {
          int th = ((Integer) it.next()).intValue();
          if (!ts[th].isAlive()) {
            logger.log(BasicLevel.DEBUG, th + " is late but ok.");
            it.remove();
          }
        }
      }
      execTime = System.currentTimeMillis() - execTime;     
      if (al.size() > 0) {
          logger.log(BasicLevel.INFO, "Kill alive threads");
        for (Iterator it = al.iterator(); it.hasNext();) {
          int th = ((Integer) it.next()).intValue();
          if (!ts[th].isAlive()) {
            it.remove();
          } else {
              try {
                            ts[th].interrupt();
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
          }
        }
        fail("Thread " + al + " blocked!");
      }
    } catch (InterruptedException e) {
      //fail(e.getMessage());
    } finally {
        if (al.size() == 0) {
        logger.log(BasicLevel.DEBUG, "Auto cleaning");
            pm = pmf.getPersistenceManager();
            ba = (BasicA) pm.getObjectById(id, false);
            val = ba.readF2();
            pm.currentTransaction().begin();
            pm.deletePersistent(ba);
            pm.currentTransaction().commit();
            pm.close();
            int nbCommittedTx = nbThread*actions.length - errors.size() - rollbackExceptions.size();
            logger.log(BasicLevel.INFO, "Commited transaction rate: "
                    + ((nbCommittedTx * 100) / (nbThread*actions.length)) + "%"
                    + ", exec time: " + execTime + "ms"
                    + ", tx/s:" + ((nbCommittedTx * 1000)/execTime));
        }
    }
    if (errors.size() > 0) {
      fail("There are " + errors.size() + "/" + nbThread + " errors during the run");
    }
      if (al.size() == 0) {
          Assert.assertEquals("Bad f2 value",
                  initialValue + nbThread*actions.length - rollbackExceptions.size(), val);
      }
  }


 
 
  private static String getDG(PersistenceManagerFactory pmf) {
    Map m = null;
    try {
            m = ((AbstractSpeedo) pmf).getDependencyGraph().getVertexes();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    if (m.size() == 0) {
        return null;
    }
    StringBuffer sb = new StringBuffer("dependency Graph: ");
      List waiters = new ArrayList(m.keySet());
      Set s = new HashSet(waiters.size() * 2);
      s.addAll(m.keySet());
      for (Iterator it = ((Collection) m.values()).iterator(); it.hasNext();) {
        s.addAll((Collection) it.next());
      }         
      List all = new ArrayList(s);
      for (int i = 0; i <all.size() ; i++) {
          Object t1 = all.get(i);
          int t1Idx = all.indexOf(t1);
          Collection dependencies = (Collection) m.get(t1);
          if (dependencies != null) {
          for (Iterator it = dependencies.iterator(); it.hasNext();) {
              sb.append("\nws");
              sb.append(t1Idx);
              sb.append(" = > ");
              sb.append("ws");
              sb.append(all.indexOf(it.next()));
          }         
          }
      }
    return sb.toString();
  }

}
TOP

Related Classes of org.objectweb.speedo.runtime.concurrency.TestManyUsers

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.