mirror of
https://github.com/berkeleydb/je.git
synced 2024-11-15 01:46:24 +00:00
265 lines
9.6 KiB
Java
265 lines
9.6 KiB
Java
|
/*-
|
|||
|
* Copyright (C) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
|||
|
*
|
|||
|
* This file was distributed by Oracle as part of a version of Oracle Berkeley
|
|||
|
* DB Java Edition made available at:
|
|||
|
*
|
|||
|
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
|
|||
|
*
|
|||
|
* Please see the LICENSE file included in the top-level directory of the
|
|||
|
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
|
|||
|
* license and additional information.
|
|||
|
*/
|
|||
|
|
|||
|
import java.io.File;
|
|||
|
|
|||
|
import com.sleepycat.je.DatabaseException;
|
|||
|
import com.sleepycat.je.DbInternal;
|
|||
|
import com.sleepycat.je.EnvironmentConfig;
|
|||
|
import com.sleepycat.je.StatsConfig;
|
|||
|
import com.sleepycat.je.rep.RepInternal;
|
|||
|
import com.sleepycat.je.rep.ReplicatedEnvironment;
|
|||
|
import com.sleepycat.je.rep.ReplicationMutableConfig;
|
|||
|
import com.sleepycat.je.rep.utilint.RepTestUtils;
|
|||
|
import com.sleepycat.je.rep.utilint.RepTestUtils.RepEnvInfo;
|
|||
|
import com.sleepycat.je.utilint.VLSN;
|
|||
|
import com.sleepycat.persist.EntityStore;
|
|||
|
import com.sleepycat.persist.StoreConfig;
|
|||
|
|
|||
|
/**
|
|||
|
* Utility methods to support replication standalone tests.
|
|||
|
*/
|
|||
|
public class Utils {
|
|||
|
public static final boolean VERBOSE = Boolean.getBoolean("verbose");
|
|||
|
public static final String DB_NAME = "testDb";
|
|||
|
|
|||
|
/**
|
|||
|
* Create an EnvironmentConfig for ReplicatedEnvironments.
|
|||
|
*/
|
|||
|
public static EnvironmentConfig createEnvConfig(long fileSize,
|
|||
|
long maxDisk,
|
|||
|
long checkpointBytes,
|
|||
|
int subDir,
|
|||
|
long mainCacheSize,
|
|||
|
long offHeapCacheSize) {
|
|||
|
EnvironmentConfig envConfig =
|
|||
|
RepTestUtils.createEnvConfig(RepTestUtils.DEFAULT_DURABILITY);
|
|||
|
|
|||
|
envConfig.setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "true");
|
|||
|
|
|||
|
/*
|
|||
|
* Set smaller log file max size and checkpointer interval bytes, so
|
|||
|
* that the log cleaning takes place in this test.
|
|||
|
*/
|
|||
|
DbInternal.disableParameterValidation(envConfig);
|
|||
|
|
|||
|
envConfig.setConfigParam(
|
|||
|
EnvironmentConfig.LOG_FILE_MAX,
|
|||
|
String.valueOf(fileSize));
|
|||
|
|
|||
|
envConfig.setConfigParam(
|
|||
|
EnvironmentConfig.CHECKPOINTER_BYTES_INTERVAL,
|
|||
|
String.valueOf(checkpointBytes));
|
|||
|
|
|||
|
if (maxDisk != 0) {
|
|||
|
envConfig.setConfigParam(
|
|||
|
EnvironmentConfig.MAX_DISK, String.valueOf(maxDisk));
|
|||
|
|
|||
|
/* Set a small FREE_DISK since it is subtracted from MAX_DISK. */
|
|||
|
envConfig.setConfigParam(
|
|||
|
EnvironmentConfig.FREE_DISK, String.valueOf(1 << 20));
|
|||
|
}
|
|||
|
|
|||
|
if (subDir > 0) {
|
|||
|
envConfig.setConfigParam
|
|||
|
(EnvironmentConfig.LOG_N_DATA_DIRECTORIES, subDir + "");
|
|||
|
}
|
|||
|
|
|||
|
envConfig.setCacheSize(mainCacheSize);
|
|||
|
envConfig.setOffHeapCacheSize(offHeapCacheSize);
|
|||
|
|
|||
|
return envConfig;
|
|||
|
}
|
|||
|
|
|||
|
/* Start up the group and return the generated RepEnvInfo array. */
|
|||
|
static RepEnvInfo[] setupGroup(File envRoot,
|
|||
|
int nNodes,
|
|||
|
long fileSize,
|
|||
|
long maxDisk,
|
|||
|
long checkpointBytes,
|
|||
|
int subDir,
|
|||
|
long mainCacheSize,
|
|||
|
long offHeapCacheSize)
|
|||
|
throws Exception {
|
|||
|
|
|||
|
RepEnvInfo[] repEnvInfo = RepTestUtils.setupEnvInfos(
|
|||
|
envRoot, nNodes,
|
|||
|
createEnvConfig(
|
|||
|
fileSize, maxDisk, checkpointBytes, subDir, mainCacheSize,
|
|||
|
offHeapCacheSize));
|
|||
|
|
|||
|
if (subDir > 0) {
|
|||
|
RepTestUtils.createRepSubDirs(repEnvInfo, subDir);
|
|||
|
}
|
|||
|
|
|||
|
if (nNodes == 2) {
|
|||
|
repEnvInfo[0].getRepConfig().setDesignatedPrimary(true);
|
|||
|
}
|
|||
|
|
|||
|
return repEnvInfo;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Join the ReplicatedEnvironments of a group of RepEnvInfo and return the
|
|||
|
* authoritative master (wait for election to quiesce).
|
|||
|
*/
|
|||
|
public static ReplicatedEnvironment getMaster(RepEnvInfo[] repEnvInfo) {
|
|||
|
return RepTestUtils.getMaster(repEnvInfo, true /*openIfNeeded*/);
|
|||
|
}
|
|||
|
|
|||
|
public static ReplicatedEnvironment assignMaster(RepEnvInfo[] repEnvInfo,
|
|||
|
int masterId,
|
|||
|
boolean restart)
|
|||
|
throws Exception {
|
|||
|
|
|||
|
assert repEnvInfo.length == 2 :
|
|||
|
"This method can only be called by a replication group size of 2.";
|
|||
|
|
|||
|
ReplicationMutableConfig newConfig = new ReplicationMutableConfig();
|
|||
|
newConfig.setDesignatedPrimary(true);
|
|||
|
|
|||
|
if (restart) {
|
|||
|
repEnvInfo[masterId - 1].getRepConfig().setDesignatedPrimary(false);
|
|||
|
repEnvInfo[masterId - 1].openEnv();
|
|||
|
} else {
|
|||
|
repEnvInfo[2 - masterId].getEnv().setRepMutableConfig(newConfig);
|
|||
|
}
|
|||
|
|
|||
|
assert repEnvInfo[2 - masterId].getEnv().getState().isMaster() :
|
|||
|
"Can't find out a master.";
|
|||
|
|
|||
|
return repEnvInfo[2 - masterId].getEnv();
|
|||
|
}
|
|||
|
|
|||
|
/* Create or open a database for test. */
|
|||
|
public static EntityStore openStore(ReplicatedEnvironment repEnv,
|
|||
|
String dbName)
|
|||
|
throws DatabaseException {
|
|||
|
|
|||
|
StoreConfig config = new StoreConfig();
|
|||
|
config.setAllowCreate(true);
|
|||
|
config.setTransactional(true);
|
|||
|
|
|||
|
return new EntityStore(repEnv, dbName, config);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Sync replicas to the master, and check that all nodes have the same
|
|||
|
* contents.
|
|||
|
*/
|
|||
|
public static void doSyncAndCheck(RepEnvInfo[] replicators)
|
|||
|
throws Exception {
|
|||
|
|
|||
|
/* Do the sync and check the node equality. */
|
|||
|
VLSN commitVLSN =
|
|||
|
RepTestUtils.syncGroupToLastCommit(replicators,
|
|||
|
replicators.length);
|
|||
|
RepTestUtils.checkNodeEquality(commitVLSN, VERBOSE, replicators);
|
|||
|
}
|
|||
|
|
|||
|
/* Check the log cleaning and close the replicas. */
|
|||
|
public static void closeEnvAndCheckLogCleaning(RepEnvInfo[] repEnvInfo,
|
|||
|
long[] fileDeletions,
|
|||
|
boolean checkCleaning)
|
|||
|
throws Exception {
|
|||
|
|
|||
|
/* Initiate an array for saving the largest log file number. */
|
|||
|
long [] lastFileNumbers = new long[repEnvInfo.length];
|
|||
|
|
|||
|
if (checkCleaning) {
|
|||
|
/* Get the cleaner deletion stat for all replicas. */
|
|||
|
int index = 0;
|
|||
|
|
|||
|
/* A stats config for getting stats. */
|
|||
|
StatsConfig stConfig = new StatsConfig();
|
|||
|
stConfig.setFast(true);
|
|||
|
stConfig.setClear(true);
|
|||
|
|
|||
|
for (RepEnvInfo repInfo : repEnvInfo) {
|
|||
|
if (repInfo.getEnv() != null &&
|
|||
|
repInfo.getEnv().isValid()) {
|
|||
|
ReplicatedEnvironment repEnv = repInfo.getEnv();
|
|||
|
fileDeletions[index] +=
|
|||
|
repEnv.getStats(stConfig).getNCleanerDeletions();
|
|||
|
/* Get largest log file number for each environment. */
|
|||
|
lastFileNumbers[index] =
|
|||
|
RepInternal.getNonNullRepImpl(repEnv).
|
|||
|
getFileManager().getLastFileNum();
|
|||
|
}
|
|||
|
index++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* Shut down the replicas. */
|
|||
|
RepTestUtils.shutdownRepEnvs(repEnvInfo);
|
|||
|
|
|||
|
if (checkCleaning) {
|
|||
|
/* Check if there is replica doesn't do log cleaning. */
|
|||
|
for (int i = 0; i < fileDeletions.length; i++) {
|
|||
|
System.err.println("Deleted files on replica " + i + " = " +
|
|||
|
fileDeletions[i]);
|
|||
|
System.err.println("Total used log files on replica " + i +
|
|||
|
" = " + (lastFileNumbers[i] + 1));
|
|||
|
if ((fileDeletions[i] * 100) / (lastFileNumbers[i] + 1) < 40) {
|
|||
|
throw new IllegalStateException
|
|||
|
("Expect to see log cleaning on replica " + i +
|
|||
|
" exceeds 40%, but it doesn't.");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void createSubDirs(File envHome, int subDirNumber) {
|
|||
|
createSubDirs(envHome, subDirNumber, false);
|
|||
|
}
|
|||
|
|
|||
|
public static void createSubDirs(File envHome,
|
|||
|
int subDirNumber,
|
|||
|
boolean useExistEnvHome) {
|
|||
|
if (!envHome.exists()) {
|
|||
|
throw new IllegalStateException
|
|||
|
("The environment home is not created yet.");
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 1; i <= subDirNumber; i++) {
|
|||
|
String fileName = null;
|
|||
|
if (i < 10) {
|
|||
|
fileName = "data00" + i;
|
|||
|
} else if (i < 100) {
|
|||
|
fileName = "data0" + i;
|
|||
|
} else if (i <= 256) {
|
|||
|
fileName = "data" + i;
|
|||
|
} else {
|
|||
|
throw new IllegalArgumentException
|
|||
|
("The number of sub directories is invalid.");
|
|||
|
}
|
|||
|
|
|||
|
File subDir = new File(envHome, fileName);
|
|||
|
|
|||
|
if (subDir.exists() && useExistEnvHome) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (subDir.exists()) {
|
|||
|
throw new IllegalStateException
|
|||
|
("The sub directories shouldn't be created yet.");
|
|||
|
}
|
|||
|
|
|||
|
if (!subDir.mkdir()) {
|
|||
|
throw new IllegalStateException
|
|||
|
("The sub directories are not created successfully.");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|