Package com.sleepycat.je.recovery

Source Code of com.sleepycat.je.recovery.RecoveryCheckpointTest

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2005
*      Sleepycat Software.  All rights reserved.
*
* $Id: RecoveryCheckpointTest.java,v 1.34 2005/09/23 19:14:58 mark Exp $
*/

package com.sleepycat.je.recovery;

import java.util.Hashtable;

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.EnvironmentStats;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.StatsConfig;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.dbi.DatabaseId;
import com.sleepycat.je.dbi.DatabaseImpl;
import com.sleepycat.je.dbi.DbTree;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.junit.JUnitThread;
import com.sleepycat.je.util.TestUtils;

public class RecoveryCheckpointTest extends RecoveryTestBase {

    volatile int sequence = 0;

    public void setExtraProperties()
  throws DatabaseException {

        /*
         * Make sure that the environments in this unit test always run with
         * checkpointing off, so we can call it explcitly.
         */
        envConfig.setConfigParam
            (EnvironmentParams.ENV_RUN_CHECKPOINTER.getName(), "false");
  /*
        envConfig.setConfigParam
            (EnvironmentParams.JE_LOGGING_LEVEL.getName(), "CONFIG");
  */
    }

    /**
     * Run checkpoints on empty dbs.
     */
    public void testEmptyCheckpoint()
        throws Throwable {

        createEnvAndDbs(1 << 20, true, NUM_DBS);

        try {

            /*
       * Run checkpoint on empty environment. Should be the second one
       * run, the first was run by recovery when the environment was
       * opened.
       */
            env.checkpoint(forceConfig);
            EnvironmentStats stats = env.getStats(TestUtils.FAST_STATS);
            assertEquals(2, stats.getNCheckpoints());
            assertEquals(2, stats.getLastCheckpointId());

            /* Shutdown, recover. */
            Hashtable expectedData = new Hashtable(); // expected values
            closeEnv()
            recoverAndVerify(expectedData, NUM_DBS); // 0 checkpoints

            /* Another checkpoint. */
            EnvironmentConfig envConfig = TestUtils.initEnvConfig();
            envConfig.setTransactional(true);
      envConfig.setConfigParam
    (EnvironmentParams.JE_LOGGING_LEVEL.getName(), "CONFIG");
            env = new Environment(envHome, envConfig);
            env.checkpoint(forceConfig);
            stats = env.getStats(TestUtils.FAST_STATS);
            assertEquals(2, stats.getNCheckpoints());
            assertEquals(4, stats.getLastCheckpointId());

            /* Shutdown, recover. */
            env.close();
            recoverAndVerify(expectedData, NUM_DBS);
        } catch (Throwable t) {
            t.printStackTrace();
            throw t;
        }
    }

    /**
     * Run checkpoints on empty dbs.
     */
    public void testNoCheckpointOnOpenSR11861()
        throws Throwable {

        createEnvAndDbs(1 << 20, true, NUM_DBS);

        try {

            EnvironmentStats stats = env.getStats(TestUtils.FAST_STATS);
            assertEquals(1, stats.getNCheckpoints());
            assertEquals(1, stats.getLastCheckpointId());

            /* Shutdown, recover. */
            Hashtable expectedData = new Hashtable(); // expected values
            Transaction txn = env.beginTransaction(null, null);
      insertData(txn, 0, 1, expectedData, 1, true, NUM_DBS);
      txn.commit();
            closeEnv();   // closes without a checkpoint
            recoverAndVerify(expectedData, NUM_DBS); // 1 checkpoint

            EnvironmentConfig envConfig = TestUtils.initEnvConfig();
            envConfig.setTransactional(true);
            env = new Environment(envHome, envConfig);
            stats = env.getStats(TestUtils.FAST_STATS);
            assertEquals(0, stats.getNCheckpoints());
            assertEquals(2, stats.getLastCheckpointId());
      env.close();
            env = new Environment(envHome, envConfig);
            stats = env.getStats(TestUtils.FAST_STATS);
            assertEquals(0, stats.getNCheckpoints());
            assertEquals(2, stats.getLastCheckpointId());

            /* Shutdown, recover. */
            env.close();
            recoverAndVerify(expectedData, NUM_DBS);
        } catch (Throwable t) {
            t.printStackTrace();
            throw t;
        }
    }

    /**
     * Test checkpoints that end up using BINDeltas -- the recovery must work.
     */
    public void testBinDelta()
  throws Throwable {

        doTestBinDelta(true);
    }

    /**
     * Same as testBinDelta but disallows deltas, to ensure that the
     * setMinimizeRecoveryTime API works.
     */
    public void testNoBinDelta()
  throws Throwable {

        doTestBinDelta(false);
    }

    private void doTestBinDelta(boolean useDeltas)
  throws Throwable {

  createEnvAndDbs(1 << 20, false, NUM_DBS);

        StatsConfig statsConfig = new StatsConfig();
        statsConfig.setClear(true);

        CheckpointConfig deltaConfig = new CheckpointConfig();
        deltaConfig.setForce(true);
        deltaConfig.setMinimizeRecoveryTime(!useDeltas);

        try {
           
            /*
             * Insert 4 records (nodeMax is 6), checkpoint, then insert 1
             * record.  The 1 record insertion will qualify for a delta,
             * because the threshold percentage is 25%, and 25% of 4 is 1.
             */
            int numRecs = 4;
            Hashtable expectedData = new Hashtable();
            Transaction txn = env.beginTransaction(null, null);
            insertData(txn, 0, numRecs, expectedData, 1, true, NUM_DBS);
            env.checkpoint(forceConfig);
            insertData(txn, numRecs+1, numRecs+2, expectedData,
           1, true, NUM_DBS);
            txn.commit();
           
            /*
             * If useDeltas is true, this next checkpoint will end up using a
             * BINDelta to log the last inserted record. It will have
             * practically nothing but the root in the checkpoint.
             */
            EnvironmentStats stats = env.getStats(statsConfig);
            env.checkpoint(deltaConfig);
            stats = env.getStats(statsConfig);
            if (useDeltas) {
                assertTrue(stats.getNDeltaINFlush() > 0);
            } else {
                assertTrue(stats.getNDeltaINFlush() == 0);
            }

            /* Shutdown, recover from a checkpoint that uses BINDeltas. */
            closeEnv();
            recoverAndVerify(expectedData, NUM_DBS);
        } catch (Throwable t) {
            t.printStackTrace();
            throw t;
        }
    }

    /**
     * Test the rollback of transactions that are active during a checkpoint.
     */
    public void testActiveWhileCheckpointing()
        throws Throwable {

  createEnvAndDbs(1 << 20, true, NUM_DBS);

        try {
            int numRecs = 1;
            Hashtable expectedData = new Hashtable();
            Transaction txn = env.beginTransaction(null, null);
            insertData(txn, 0, numRecs, expectedData, 1, false, NUM_DBS);

            /* Now run a checkpoint while this operation hasn't finished. */
            env.checkpoint(forceConfig);
            txn.abort();
           
            /* Shutdown, recover. */
            closeEnv();
            recoverAndVerify(expectedData, NUM_DBS);
        } catch (Throwable t) {
            t.printStackTrace();
            throw t;
        }
    }

    public void testSR11293()
  throws Throwable {

  createEnv(1 << 20, false);

  Transaction dbTxn = env.beginTransaction(null, null);
  EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
  final DbTree dbTree = envImpl.getDbMapTree();

        DatabaseConfig dbConfig = new DatabaseConfig();
        dbConfig.setTransactional(true);
        dbConfig.setAllowCreate(true);
        dbConfig.setSortedDuplicates(true);
  final Database db = env.openDatabase(dbTxn, "foo", dbConfig);
  dbTxn.commit();
  final Transaction txn = env.beginTransaction(null, null);
  sequence = 0;

  /**
   * The sequence between the two tester threads is:
   *
   * tester2: write 1/1 into the database.  This causes the initial tree
   * to be created (IN/BIN/LN).  Flush that out to the disk with a full
   * checkpoint.  Signal tester1 and wait.
   *
   * tester1: Lock the MapLN for "foo" db.  Signal tester2 and wait.
   *
   * tester2: Add 2/2 to the tree which causes the BIN to be dirtied.
   * Signal tester1 to continue, perform a full checkpoint which will
   * causes the root IN to be dirtied and flushed.  DbTree.modifyDbRoot
   * will block on the MapLN lock held by tester1.
   *
   * tester1: while tester2 is blocking on the MapLN lock, this thread is
   * sleeping.  When it wakes up, it releases the MapLN lock by aborting
   * the transaction.
   *
   * tester2: modifyDbRoot finally acquires the write lock on foo-db's
   * MapLN write lock, performs the update to the DbTree and returns from
   * the sync().
   */
  JUnitThread tester1 =
      new JUnitThread("testSR11293DbTreeLocker") {
        public void testBody() {
      try {
          /* Wait for tester2. */
          while (sequence < 1) {
        Thread.yield();
          }

          /* Lock the MapLN for the database. */
          DatabaseId fooId =
        DbInternal.dbGetDatabaseImpl(db).getId();
          DatabaseImpl fooDb = dbTree.getDb(fooId, 500000L);
          assert fooDb != null;

          sequence++;

          /* Wait for tester2. */
          while (sequence < 3) {
        Thread.yield();
          }

          try {
        Thread.sleep(3000);
          } catch (Exception E) {
          }

          try {
        txn.abort();
        db.close();
        env.close();
          } catch (DatabaseException DBE) {
        DBE.printStackTrace();
        fail("unexpected exception: " + DBE);
          }
      } catch (DatabaseException DBE) {
          DBE.printStackTrace();
          fail("caught DatabaseException " + DBE);
      }
        }
    };

  JUnitThread tester2 =
      new JUnitThread("testSR11293DbWriter") {
        public void testBody() {
      try {
          DatabaseEntry key =
        new DatabaseEntry(new byte[] { 1 });
          DatabaseEntry data =
        new DatabaseEntry(new byte[] { 1 });
          assertEquals(OperationStatus.SUCCESS,
           db.put(null, key, data));
          env.sync();

          sequence++;
          while (sequence < 2) {
        Thread.yield();
          }

          key.setData(new byte[] { 2 });
          data.setData(new byte[] { 2 });
          assertEquals(OperationStatus.SUCCESS,
           db.put(null, key, data));
          sequence++;
          env.sync();
      } catch (DatabaseException DBE) {
          DBE.printStackTrace();
          fail("unexpected exception: " + DBE);
      }
        }
    };

  tester1.start();
  tester2.start();
  tester1.finishTest();
  tester2.finishTest();

        EnvironmentConfig recoveryConfig = TestUtils.initEnvConfig();

        recoveryConfig.setConfigParam
      (EnvironmentParams.ENV_RUN_CHECKPOINTER.getName(), "false");
  recoveryConfig.setConfigParam
      (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false");
  recoveryConfig.setConfigParam
      (EnvironmentParams.ENV_RUN_EVICTOR.getName(), "false");

        env = new Environment(envHome, recoveryConfig);
  dbConfig.setAllowCreate(false);
  dbConfig.setTransactional(false);
  Database db2 = env.openDatabase(null, "foo", dbConfig);
  Cursor c = db2.openCursor(null, null);
  DatabaseEntry key = new DatabaseEntry();
  DatabaseEntry data = new DatabaseEntry();
  assertEquals(OperationStatus.SUCCESS,
         c.getNext(key, data, LockMode.DEFAULT));
  assertEquals((key.getData())[0], 1);
  assertEquals((data.getData())[0], 1);

  assertEquals(OperationStatus.SUCCESS,
         c.getNext(key, data, LockMode.DEFAULT));
  assertEquals((key.getData())[0], 2);
  assertEquals((data.getData())[0], 2);
  assertEquals(OperationStatus.NOTFOUND,
         c.getNext(key, data, LockMode.DEFAULT));

  c.close();
  db2.close();
  env.close();
    }

    /*
     * See what happens if someone calls checkpoint on a read only environment.
     */
    public void testReadOnlyCheckpoint()
        throws DatabaseException {
        /* Create an environment, close. */
        EnvironmentConfig c = TestUtils.initEnvConfig();
        c.setAllowCreate(true);
        Environment e = new Environment(envHome, c);
        e.close();

        /* Now open read only. */
        c.setAllowCreate(false);
        c.setReadOnly(true);
        e = new Environment(envHome, c);
        try {
            CheckpointConfig ckptConfig = new CheckpointConfig();
            ckptConfig.setForce(true);
            e.checkpoint(ckptConfig);
        } finally {
            e.close();
        }
    }
}
TOP

Related Classes of com.sleepycat.je.recovery.RecoveryCheckpointTest

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.