Package com.sleepycat.je.incomp

Source Code of com.sleepycat.je.incomp.EmptyBINTest$PruningHook

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2005
*      Sleepycat Software.  All rights reserved.
*
* $Id: EmptyBINTest.java,v 1.3 2005/08/04 18:53:15 cwl Exp $
*/

package com.sleepycat.je.incomp;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;

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

import com.sleepycat.je.CheckpointConfig;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.DbInternal;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.dbi.CursorImpl;
import com.sleepycat.je.util.TestUtils;
import com.sleepycat.je.utilint.TestHook;

/**
* Test that searches and cursor traversals execute correctly in the face of
* a BIN with 0 entries, and with tree pruning at key points.
*/
public class EmptyBINTest extends TestCase {
    private static final boolean DEBUG = false;

    private static final byte DEFAULT_VAL = 100;
    private File envHome;
    private Environment env;
    private Database db;

    private boolean useDups;
    private boolean doPruningAtCursorLevel;
    private boolean doPruningAtTreeLevel;

    public EmptyBINTest() {
        envHome = new File(System.getProperty(TestUtils.DEST_DIR));
    }

    public void setUp()
        throws IOException {

        TestUtils.removeLogFiles("Setup", envHome, false);
    }
   
    public void tearDown()
        throws Exception {

        if (db != null) {
            try {
    db.close();
      } catch (DatabaseException ignore) {
      }
        }

        if (env != null) {
            try {
    env.close();
      } catch (DatabaseException ignore) {
      }
        }
        env = null;
        db = null;
        setName(getName() + "-" +
    (useDups ? "DUPS" : "!DUPS") +
    "/" +
    (doPruningAtCursorLevel ? "CURSORPRUNE" : "!CURSORPRUNE") +
    "/" +
    (doPruningAtTreeLevel ? "TREEPRUNE" : "!TREEPRUNE"));
  super.tearDown();
        TestUtils.removeLogFiles("TearDown", envHome, false);
    }

    /*
     * Run all tests in four combinations, using dups, and invoking bin
     * pruning.
     */
    public static Test suite() {
        TestSuite allTests = new TestSuite();
        boolean[] dupCombo = new boolean[] {true, false};
        boolean[] pruneCombo = new boolean[] {true, false};
        for (int dup = 0; dup < dupCombo.length; dup++) {
            for (int pruneCursor = 0;
     pruneCursor < pruneCombo.length;
     pruneCursor++) {
    for (int pruneTree = 0;
         pruneTree < pruneCombo.length;
         pruneTree++) {
        TestSuite suite = new TestSuite(EmptyBINTest.class);
        Enumeration e = suite.tests();
        while (e.hasMoreElements()) {
      EmptyBINTest test = (EmptyBINTest) e.nextElement();
      boolean pruneC = pruneCombo[pruneCursor];
      boolean pruneT = pruneCombo[pruneTree];
      if (pruneC && pruneT) {
          /* Only do one hook at a time. */
          break;
      }
      test.init(dupCombo[dup], pruneC, pruneT);
      allTests.addTest(test);
        }
    }
      }
        }
        return allTests;
    }

    private void init(boolean useDups,
          boolean doPruningAtCursorLevel,
          boolean doPruningAtTreeLevel) {
        this.useDups = useDups;
        this.doPruningAtCursorLevel = doPruningAtCursorLevel;
        this.doPruningAtTreeLevel = doPruningAtTreeLevel;
        if (DEBUG) {
            System.out.println("useDups=" + useDups +
                               " doPruningAtCursorLevel=" +
             doPruningAtCursorLevel +
                               " doPruningAtTreeLevel=" +
             doPruningAtTreeLevel);
        }
    }

    /* Non-dupes scans across an empty BIN. */
    public void testScanFromEndOfFirstBin()
        throws DatabaseException {

  /*
         * Tree holds <0,1>  <2,3,4> <empty> <8,9,10>.
         *                        |
         *   fwd scan starts --- -+
         * Fwd scan starting at 4.  Expect 4, 8, 9, 10
         */
        doScanAcrossEmptyBin(true,      // forward
                             (byte) 4// start
                             new byte[] {4,8,9,10}); // expected
    }

    public void testScanFromLeftSideOfEmptyBin()
        throws DatabaseException {

  /*
         * Tree holds <0,1>  <2,3,4> <empty> <8,9,10>.
         *                            |
         *   scan starts -------------+
         * Fwd scan starting at 5 (deleted).  Expect 8, 9, 10
         */
        doScanAcrossEmptyBin(true,       // forward
                             (byte) 5,   // start
                             new byte[] {8,9,10}); // expected
    }

    public void testScanFromRightSideOfEmptyBin()
        throws DatabaseException {

  /*
         * Tree holds <0,1>  <2,3,4> <empty> <8,9,10>.
         *                                |
         *   backwards scan starts ------+
         * Backwards scan starting at 7 (deleted).  Expect 8,4,3,2,1,0
         */
        doScanAcrossEmptyBin(false,      // backwards
                             (byte) 7,   // start
                             new byte[] {8,4,3,2,1,0}); // expected
    }

    public void testScanFromBeginningOfLastBin()
        throws DatabaseException {

  /*
         * Tree holds <0,1>  <2,3,4> <empty> <8,9,10>.
         *                                    |
         *   backwards scan starts -----------+
         */
        doScanAcrossEmptyBin(false,      // backwards
                             (byte) 8,   // start
                             new byte[] {8,4,3,2,1,0})// expected vals
    }

    public void testScanForward()
        throws DatabaseException {

  /*
         * Tree holds <0,1>  <2,3,4> <empty> <8,9,10>.
         * Fwd scan starting with first.  Expect 0, 1, 2, 4, 8, 9, 10.
         */
        doScanAcrossEmptyBin(true,    // forward
                             (byte) -1,
                             new byte[] {0,1,2,3,4,8,9,10});
    }

    public void testScanBackwards()
        throws DatabaseException {

  /*
         * Tree holds <0,1>  <2,3,4> <empty> <8,9,10>.
         * Bwd scan starting with last. 10 -> 0
         */
        doScanAcrossEmptyBin(false,   // backwards
                             (byte) -1,
                             new byte[] {10,9,8,4,3,2,1,0});
    }

    /**
     * Scan over an empty BIN that is in the middle of the tree. [#11778]
     * The tree holds values from 0 - 10. Values 5, 6, 7 have been deleted.
     * @param forward indicates use getNext().
     * @param startKey >= 0 indicates do getSearchKeyRange to init cursor.
     * @param expectVals are the elements to expect find
     */
    private void doScanAcrossEmptyBin(boolean forward,
              byte startKey,
                                      byte[] expectVals)
        throws DatabaseException {

        int deleteStartVal = 5;
        int deleteEndVal = 7;
        openAndInitEmptyMiddleBIN(deleteStartVal, deleteEndVal);

        if (DEBUG) {
      DbInternal.dbGetDatabaseImpl(db).getTree().dump();
        }

        DatabaseEntry key = new DatabaseEntry();
        DatabaseEntry data = new DatabaseEntry();

  /*
   * Position a cursor and check that we get the expected values.
   */
  int cnt = 0;
        Cursor cursor = db.openCursor(null, null);
        CursorImpl cursorImpl = DbInternal.getCursorImpl(cursor);

        if (doPruningAtCursorLevel) {
            cursorImpl.setTestHook(new PruningHook(env));
        }

        if (doPruningAtTreeLevel) {
            DbInternal.dbGetDatabaseImpl(db).getTree().
    setSearchHook(new PruningHook(env));
        }

        int expectIndex = 0;
  if (startKey < 0) {
      if (forward) {
    assertEquals(OperationStatus.SUCCESS,
                             cursor.getFirst(key, data, null));
      } else {
    assertEquals(OperationStatus.SUCCESS,
                             cursor.getLast(key, data, null));
      }
  } else {
            if (useDups) {
                key.setData(new byte[] {DEFAULT_VAL});
                data.setData(new byte[] {startKey});
            } else {
                key.setData(new byte[] { startKey });
            }
               
      if ((startKey >= deleteStartVal) &&
    (startKey <= deleteEndVal)) {
    /* Test range query. */
                if (useDups) {
                    assertEquals(OperationStatus.SUCCESS,
                                 cursor.getSearchBothRange(key, data, null));
                } else {
                    assertEquals(OperationStatus.SUCCESS,
                                 cursor.getSearchKeyRange(key, data, null));
                }
      } else {
    /* Test from getSearchKey(). */
                if (useDups) {
                    assertEquals(OperationStatus.SUCCESS,
                                 cursor.getSearchBoth(key, data, null));
                } else {
                    assertEquals(OperationStatus.SUCCESS,
                                 cursor.getSearchKey(key, data, null));
                }
      }
  }

        OperationStatus status;
        do {
            cnt++;           

            /* check value. */
            if (DEBUG) {
                System.out.println("=>key=" + key.getData()[0] +
                                   " data=" + data.getData()[0]);
            }
            if (useDups) {
                assertEquals(expectVals[expectIndex++], data.getData()[0]);
            } else {
                assertEquals(expectVals[expectIndex++], key.getData()[0]);
            }

      if (forward) {
    status = cursor.getNext(key, data, null);
      } else {
    status = cursor.getPrev(key, data, null);
            }
        } while (status == OperationStatus.SUCCESS);

  assertEquals(expectVals.length, cnt);
  cursor.close();
        closeEnv();
    }

    /**
     * Create a tree with:
     *                         IN
     *                      /     \
     *                    IN       IN
     *                    / \     /   \
     *                BIN1 BIN2  BIN3 BIN4
     *
     * where BIN1 has values 0,1
     *       BIN2 has valus 2,3,4
     *       BIN3 has valus 5,6,7
     *       BIN4 has valus 8,9,10
     * Depending on configuration, the entries in BIN2 or BIN3
     */
    private void openAndInitEmptyMiddleBIN(int deleteStartVal,
                                           int deleteEndVal)
        throws DatabaseException {

        openEnv(false, "4");
        DatabaseEntry data = new DatabaseEntry();
        data.setData(new byte[] {DEFAULT_VAL});
        DatabaseEntry key = new DatabaseEntry();
        key.setData(new byte[] {DEFAULT_VAL});

        /* Create four BINs */
        OperationStatus status;
        for (int i = 0; i < 11; i++) {
            if (useDups) {
                data = new DatabaseEntry(new byte[] { (byte) i });
            } else {
                key = new DatabaseEntry(new byte[] { (byte) i });
            }
            status = db.put(null, key, data);
            assertEquals(OperationStatus.SUCCESS, status);
  }

        /* Empty out one of the middle ones. */
        if (useDups) {
            Cursor cursor = db.openCursor(null, null);
            data = new DatabaseEntry(new byte[] { (byte) deleteStartVal });
            assertEquals(OperationStatus.SUCCESS,
                         cursor.getSearchBoth(key, data, LockMode.DEFAULT));
            for (int i = deleteStartVal; i <= deleteEndVal; i++) {
                assertEquals(OperationStatus.SUCCESS,
                             cursor.delete());
                assertEquals(OperationStatus.SUCCESS,
                             cursor.getNext(key, data, LockMode.DEFAULT));
            }
            cursor.close();
        } else {
            for (int i = deleteStartVal; i <= deleteEndVal; i++) {
                key = new DatabaseEntry(new byte[] { (byte) i });
                status = db.delete(null, key);
                assertEquals(OperationStatus.SUCCESS, status);
            }
        }

        CheckpointConfig config = new CheckpointConfig();
        config.setForce(true);
        env.checkpoint(config);
    }

    /**
     * Opens the environment and db.
     */
    private void openEnv(boolean transactional, String nodeMax)
        throws DatabaseException {

        EnvironmentConfig envConfig = TestUtils.initEnvConfig();
        envConfig.setTransactional(transactional);
        envConfig.setConfigParam
            (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "true");
  if (nodeMax != null) {
      envConfig.setConfigParam
    (EnvironmentParams.NODE_MAX.getName(), nodeMax);
      envConfig.setConfigParam
    (EnvironmentParams.NODE_MAX_DUPTREE.getName(), nodeMax);
  }
        envConfig.setAllowCreate(true);
        env = new Environment(envHome, envConfig);

        /* Make a db and open it. */
        DatabaseConfig dbConfig = new DatabaseConfig();
        dbConfig.setTransactional(transactional);
        dbConfig.setSortedDuplicates(useDups);
        dbConfig.setAllowCreate(true);
        db = env.openDatabase(null, "testDB", dbConfig);
    }

    /**
     * Closes the db and environment.
     */
    private void closeEnv()
        throws DatabaseException {

        db.close();
        db = null;
        env.close();
        env = null;
    }

    private static class PruningHook implements TestHook {
        Environment env;

        PruningHook(Environment env) {
            this.env = env;
        }

        public void doIOHook() throws IOException {}

        public void doHook() {
      DbInternal.envGetEnvironmentImpl(env).getINCompressor().
    wakeup();
      Thread.yield();
      try {
    Thread.sleep(100);
      } catch (Throwable T) {
      }
        }
    }
}
TOP

Related Classes of com.sleepycat.je.incomp.EmptyBINTest$PruningHook

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.