Package org.exist.storage.lock

Source Code of org.exist.storage.lock.DeadlockTest$QueryTask

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2001-07 The eXist Project
*  http://exist-db.org
*
*  This program 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 program 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*
* $Id$
*/
package org.exist.storage.lock;

import static org.junit.Assert.*;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.exist.TestDataGenerator;
import org.exist.collections.Collection;
import org.exist.collections.CollectionConfigurationManager;
import org.exist.collections.IndexInfo;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.txn.TransactionManager;
import org.exist.storage.txn.Txn;
import org.exist.test.TestConstants;
import org.exist.util.Configuration;
import org.exist.xmldb.DatabaseInstanceManager;
import org.exist.xmldb.XPathQueryServiceImpl;
import org.exist.xmldb.XmldbURI;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.After;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.xml.sax.InputSource;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.Database;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.base.Resource;
import org.xmldb.api.modules.CollectionManagementService;

/**
* Test deadlock detection and resolution.
*
* @author wolf
*/
@RunWith(Parameterized.class)
public class DeadlockTest {

  /** pick a set of random collections to query */
  private static final int TEST_RANDOM_COLLECTION = 0;
  /** pick a single collection to query */
  private static final int TEST_SINGLE_COLLECTION = 1;
  /** query the root collection */
  private static final int TEST_ALL_COLLECTIONS = 2;
  /** query a single document */
  private static final int TEST_SINGLE_DOC = 3;
  /** apply a random mixture of the other modes */
  private static final int TEST_MIXED = 4;

    private static final int TEST_REMOVE = 5;

    private static final int DELAY = 7000;

    /** Use 4 test runs, querying different collections */
  @Parameters
  public static LinkedList<Integer[]> data() {
    LinkedList<Integer[]> params = new LinkedList<Integer[]>();
    params.add(new Integer[] { TEST_RANDOM_COLLECTION });
    params.add(new Integer[] { TEST_SINGLE_COLLECTION });
    params.add(new Integer[] { TEST_ALL_COLLECTIONS });
    params.add(new Integer[] { TEST_SINGLE_DOC });
    params.add(new Integer[] { TEST_MIXED });
        params.add(new Integer[] { TEST_REMOVE });
        return params;
  }
 
  private static final int COLL_COUNT = 20;

    private static final int QUERY_COUNT = 1000;

    private static final int DOC_COUNT = 70;

    private static final int REMOVE_COUNT = 50;
   
    private static final int N_THREADS = 40;

    private final static String COLLECTION_CONFIG =
    "<collection xmlns=\"http://exist-db.org/collection-config/1.0\">" +
    "  <index>" +
        "    <lucene>" +
        "           <text match='/*'/>" +
        "       </lucene>" +
    "    <create path=\"//section/@id\" type=\"xs:string\"/>" +
    "  </index>" +
    "</collection>";
 
  private final static String generateXQ = "<book id=\"{$filename}\" n=\"{$count}\">"
      + "   <chapter>"
      + "       <title>{pt:random-text(7)}</title>"
      + "       {"
      + "           for $section in 1 to 8 return"
      + "               <section id=\"sect{$section}\">"
      + "                   <title>{pt:random-text(7)}</title>"
      + "                   {"
      + "                       for $para in 1 to 10 return"
      + "                           <para>{pt:random-text(40)}</para>"
      + "                   }"
      + "               </section>"
      + "       }"
      + "   </chapter>" + "</book>";

  private static BrokerPool pool;

  private Random random = new Random();

  private int mode = 0;
 
  public DeadlockTest(int mode) {
    this.mode = mode;
    System.out.println("MODE: " + mode);
  }
 
  @BeforeClass
  public static void startDB() {
    TransactionManager transact = null;
    Txn transaction = null;
    DBBroker broker = null;
    try {
      Configuration config = new Configuration();
      BrokerPool.configure(1, 40, config);
      pool = BrokerPool.getInstance();

      broker = pool.get(pool.getSecurityManager().getSystemSubject());
      transact = pool.getTransactionManager();
      assertNotNull(transact);
      transaction = transact.beginTransaction();
      Collection root = broker.getOrCreateCollection(transaction,
          XmldbURI.ROOT_COLLECTION_URI);
      assertNotNull(root);
      broker.saveCollection(transaction, root);

      Collection test = broker.getOrCreateCollection(transaction,
          TestConstants.TEST_COLLECTION_URI);
      assertNotNull(test);
      broker.saveCollection(transaction, test);

      CollectionConfigurationManager mgr = pool.getConfigurationManager();
            mgr.addConfiguration(transaction, broker, test, COLLECTION_CONFIG);
           
      InputSource is = new InputSource(new File(
          "samples/shakespeare/hamlet.xml").toURI().toASCIIString());
      assertNotNull(is);
      IndexInfo info = test.validateXMLResource(transaction, broker,
          XmldbURI.create("hamlet.xml"), is);
      assertNotNull(info);
      test.store(transaction, broker, info, is, false);
      transact.commit(transaction);

      // initialize XML:DB driver
      Class<?> cl = Class.forName("org.exist.xmldb.DatabaseImpl");
      Database database = (Database) cl.newInstance();
      DatabaseManager.registerDatabase(database);
    } catch (Exception e) {
      transact.abort(transaction);
      e.printStackTrace();
      fail(e.getMessage());
    } finally {
      pool.release(broker);
    }
  }

  @AfterClass
  public static void stopDB() {
    try {
      org.xmldb.api.base.Collection root = DatabaseManager.getCollection(
          "xmldb:exist:///db", "admin", null);

      DatabaseInstanceManager dim = (DatabaseInstanceManager) root.getService("DatabaseInstanceManager", "1.0");
      dim.shutdown();
    } catch (XMLDBException e) {
      e.printStackTrace();
      fail(e.getMessage());
    }
    pool = null;
  }

    @After
    public void clearDB() {
        try {
      org.xmldb.api.base.Collection root = DatabaseManager.getCollection("xmldb:exist:///db/test", "admin", null);
      CollectionManagementService service = (CollectionManagementService) root.getService("CollectionManagementService", "1.0");
      service.removeCollection(".");
        } catch (XMLDBException e) {
      e.printStackTrace();
      fail(e.getMessage());
    }
    }

    @Test
  public void runTasks() {
    ExecutorService executor = Executors.newFixedThreadPool(N_THREADS);
        executor.submit(new StoreTask("store", COLL_COUNT, DOC_COUNT));
        synchronized (this) {
            try {
                wait(DELAY);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    for (int i = 0; i < QUERY_COUNT; i++) {
      executor.submit(new QueryTask(COLL_COUNT));
    }
        if (mode == TEST_REMOVE) {
            for (int i = 0; i < REMOVE_COUNT; i++) {
                executor.submit(new RemoveDocumentTask(COLL_COUNT, DOC_COUNT));
            }
        }
        executor.shutdown();
    boolean terminated = false;
    try {
      terminated = executor.awaitTermination(60 * 60, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
    }
    assertTrue(terminated);
  }

  private static class StoreTask implements Runnable {

    @SuppressWarnings("unused")
    private String id;
    private int docCount;
    private int collectionCount;

    public StoreTask(String id, int collectionCount, int docCount) {
      this.id = id;
      this.collectionCount = collectionCount;
      this.docCount = docCount;
    }

    public void run() {
      TransactionManager transact = null;
      Txn transaction = null;
      DBBroker broker = null;
      try {
        broker = pool.get(pool.getSecurityManager().getSystemSubject());
        transact = pool.getTransactionManager();
        assertNotNull(transact);

        TestDataGenerator generator = new TestDataGenerator("xdb", docCount);
        Collection coll;
        int fileCount = 0;
        for (int i = 0; i < collectionCount; i++) {
                    transaction = transact.beginTransaction();
                    coll = broker.getOrCreateCollection(transaction,
              TestConstants.TEST_COLLECTION_URI.append(Integer
                  .toString(i)));
          assertNotNull(coll);
          broker.saveCollection(transaction, coll);
                    transact.commit(transaction);

                    transaction = transact.beginTransaction();
                    System.out.println("Generating " + docCount + " files...");
          File[] files = generator.generate(broker, coll, generateXQ);
          for (int j = 0; j < files.length; j++, fileCount++) {
            InputSource is = new InputSource(files[j].toURI()
                .toASCIIString());
            assertNotNull(is);
            IndexInfo info = coll.validateXMLResource(transaction,
                broker, XmldbURI.create("test" + fileCount
                    + ".xml"), is);
            assertNotNull(info);
            coll.store(transaction, broker, info, is, false);
                        transact.commit(transaction);
                    }
          generator.releaseAll();
        }
      } catch (Exception e) {
        transact.abort(transaction);
        e.printStackTrace();
//        fail(e.getMessage());
      } finally {
        pool.release(broker);
      }
    }
  }

  private class QueryTask implements Runnable {

    private int collectionCount;

    public QueryTask(int collectionCount) {
      this.collectionCount = collectionCount;
    }

    public void run() {
      StringBuilder buf = new StringBuilder();
      String collection = "/db";
      int currentMode = mode;
      if (mode == TEST_MIXED || currentMode == TEST_REMOVE)
        currentMode = random.nextInt(4);
            if (currentMode == TEST_SINGLE_COLLECTION) {
        int collectionId = random.nextInt(collectionCount);
        collection = "/db/test/" + collectionId;
        buf.append("collection('").append(collection)
          .append("')//chapter/section[@id = 'sect1']");
      } else if (currentMode == TEST_RANDOM_COLLECTION) {
        List<Integer> collIds = new ArrayList<Integer>(7);
        for (int i = 0; i < 3; i++) {
          int r;
          do {
            r = random.nextInt(collectionCount);
          } while (collIds.contains(r));
          collIds.add(r);
        }
        buf.append("(");
        for (int i = 0; i < 3; i++) {
          if (i > 0)
            buf.append(", ");
          buf.append("collection('/db/test/").append(collIds.get(i))
              .append("')");
        }
        buf.append(")//chapter/section[@id = 'sect1']");
        collection = "/db/test";
      } else if (currentMode == TEST_SINGLE_DOC) {
        int collectionId = random.nextInt(collectionCount);
        collection = "/db/test/" + collectionId;
        buf.append("doc('").append(collection).append("/test1.xml')//chapter/section[@id = 'sect1']");
      } else {
        buf.append("//chapter/section[@id = 'sect1']");
      }
     
      String query = buf.toString();
      System.out.println("Query: " + query);
      try {
        org.xmldb.api.base.Collection testCollection = DatabaseManager
            .getCollection("xmldb:exist://" + collection, "admin", null);
                if (testCollection == null)
                    return;
                XPathQueryServiceImpl service = (XPathQueryServiceImpl) testCollection
            .getService("XQueryService", "1.0");
        service.beginProtected();
        try {
          ResourceSet result = service.query(query);
          System.out.println("Result: " + result.getSize());
        } finally {
          service.endProtected();
        }
      } catch (Exception e) {
        e.printStackTrace();
        fail(e.getMessage());
      }
    }
  }

    private class RemoveDocumentTask implements Runnable {

        private int collectionCount;
        private int documentCount;

        public RemoveDocumentTask(int collectionCount, int documentCount) {
            this.collectionCount = collectionCount;
            this.documentCount = documentCount;
        }

        public void run() {
            boolean removed = false;
            do {
                int collectionId = random.nextInt(collectionCount);
                String collection = "/db/test/" + collectionId;
                int docId = random.nextInt(documentCount) * collectionId;
                String document = "test" + docId + ".xml";
                try {
                    org.xmldb.api.base.Collection testCollection = DatabaseManager.getCollection("xmldb:exist://" + collection, "admin", null);
                    Resource resource = testCollection.getResource(document);
                    if (resource != null) {
                        testCollection.removeResource(resource);
                        removed = true;
                    }
                } catch (XMLDBException e) {
                    e.printStackTrace();
                    fail(e.getMessage());
                }
            } while (!removed);
        }
    }
}
TOP

Related Classes of org.exist.storage.lock.DeadlockTest$QueryTask

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.