001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: BackgroundIOTest.java,v 1.4.2.3 2008/01/07 15:14:25 cwl Exp $
007: */
008:
009: package com.sleepycat.je.cleaner;
010:
011: import java.io.File;
012: import java.io.IOException;
013:
014: import junit.framework.TestCase;
015:
016: import com.sleepycat.bind.tuple.TupleBase;
017: import com.sleepycat.bind.tuple.TupleOutput;
018: import com.sleepycat.je.CheckpointConfig;
019: import com.sleepycat.je.Database;
020: import com.sleepycat.je.DatabaseConfig;
021: import com.sleepycat.je.DatabaseEntry;
022: import com.sleepycat.je.DatabaseException;
023: import com.sleepycat.je.DbInternal;
024: import com.sleepycat.je.Environment;
025: import com.sleepycat.je.EnvironmentConfig;
026: import com.sleepycat.je.config.EnvironmentParams;
027: import com.sleepycat.je.dbi.EnvironmentImpl;
028: import com.sleepycat.je.latch.LatchSupport;
029: import com.sleepycat.je.log.FileManager;
030: import com.sleepycat.je.util.TestUtils;
031: import com.sleepycat.je.utilint.TestHook;
032:
033: public class BackgroundIOTest extends TestCase {
034:
035: private static CheckpointConfig forceConfig;
036: static {
037: forceConfig = new CheckpointConfig();
038: forceConfig.setForce(true);
039: }
040:
041: private File envHome;
042: private Environment env;
043: private int nSleeps;
044:
045: public BackgroundIOTest() {
046: envHome = new File(System.getProperty(TestUtils.DEST_DIR));
047: }
048:
049: public void setUp() throws IOException, DatabaseException {
050:
051: TestUtils.removeLogFiles("Setup", envHome, false);
052: TestUtils.removeFiles("Setup", envHome, FileManager.DEL_SUFFIX);
053: }
054:
055: public void tearDown() throws IOException, DatabaseException {
056:
057: if (env != null) {
058: try {
059: env.close();
060: } catch (Throwable e) {
061: System.out.println("tearDown: " + e);
062: }
063: env = null;
064: }
065:
066: //*
067: TestUtils.removeLogFiles("TearDown", envHome, true);
068: TestUtils.removeFiles("TearDown", envHome,
069: FileManager.DEL_SUFFIX);
070: //*/
071: }
072:
073: public void testBackgroundIO1() throws DatabaseException,
074: InterruptedException {
075:
076: doTest(10, 10, 226, 246);
077: }
078:
079: public void testBackgroundIO2() throws DatabaseException,
080: InterruptedException {
081:
082: doTest(10, 5, 365, 385);
083: }
084:
085: public void testBackgroundIO3() throws DatabaseException,
086: InterruptedException {
087:
088: doTest(5, 10, 324, 344);
089: }
090:
091: public void testBackgroundIO4() throws DatabaseException,
092: InterruptedException {
093:
094: doTest(5, 5, 463, 483);
095: }
096:
097: private void doTest(int readLimit, int writeLimit, int minSleeps,
098: int maxSleeps) throws DatabaseException,
099: InterruptedException {
100:
101: final int fileSize = 1000000;
102: EnvironmentConfig envConfig = TestUtils.initEnvConfig();
103: envConfig.setAllowCreate(true);
104: envConfig.setConfigParam(EnvironmentParams.ENV_RUN_CLEANER
105: .getName(), "false");
106: envConfig.setConfigParam(EnvironmentParams.ENV_RUN_CHECKPOINTER
107: .getName(), "false");
108: envConfig.setConfigParam(EnvironmentParams.ENV_RUN_INCOMPRESSOR
109: .getName(), "false");
110: envConfig.setConfigParam(EnvironmentParams.LOG_BUFFER_MAX_SIZE
111: .getName(), Integer.toString(1024));
112: envConfig.setConfigParam(EnvironmentParams.LOG_FILE_MAX
113: .getName(), Integer.toString(fileSize));
114: envConfig.setConfigParam(
115: EnvironmentParams.CLEANER_MIN_UTILIZATION.getName(),
116: "60");
117: //*
118: envConfig.setConfigParam(
119: EnvironmentParams.ENV_BACKGROUND_READ_LIMIT.getName(),
120: String.valueOf(readLimit));
121: envConfig.setConfigParam(
122: EnvironmentParams.ENV_BACKGROUND_WRITE_LIMIT.getName(),
123: String.valueOf(writeLimit));
124: //*/
125: env = new Environment(envHome, envConfig);
126:
127: EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
128: envImpl.setBackgroundSleepHook(new TestHook() {
129: public void doHook() {
130: nSleeps += 1;
131: assertEquals(0, LatchSupport.countLatchesHeld());
132: }
133:
134: public Object getHookValue() {
135: throw new UnsupportedOperationException();
136: }
137:
138: public void doIOHook() throws IOException {
139: throw new UnsupportedOperationException();
140: }
141: });
142:
143: DatabaseConfig dbConfig = new DatabaseConfig();
144: dbConfig.setAllowCreate(true);
145: dbConfig.setExclusiveCreate(true);
146: Database db = env.openDatabase(null, "BackgroundIO", dbConfig);
147:
148: final int nFiles = 3;
149: final int keySize = 20;
150: final int dataSize = 10;
151: final int recSize = keySize + dataSize + 35 /* LN overhead */;
152: final int nRecords = nFiles * (fileSize / recSize);
153:
154: /*
155: * Insert records first so we will have a sizeable checkpoint. Insert
156: * interleaved because sequential inserts flush the BINs, and we want
157: * to defer BIN flushing until the checkpoint.
158: */
159: DatabaseEntry key = new DatabaseEntry();
160: DatabaseEntry data = new DatabaseEntry(new byte[dataSize]);
161: for (int i = 0; i <= nRecords; i += 2) {
162: setKey(key, i, keySize);
163: db.put(null, key, data);
164: }
165: for (int i = 1; i <= nRecords; i += 2) {
166: setKey(key, i, keySize);
167: db.put(null, key, data);
168: }
169:
170: /* Perform a checkpoint to perform background writes. */
171: env.checkpoint(forceConfig);
172:
173: /* Delete records so we will have a sizable cleaning. */
174: for (int i = 0; i <= nRecords; i += 1) {
175: setKey(key, i, keySize);
176: db.delete(null, key);
177: }
178:
179: /* Perform cleaning to perform background reading. */
180: env.checkpoint(forceConfig);
181: env.cleanLog();
182: env.checkpoint(forceConfig);
183:
184: db.close();
185: env.close();
186: env = null;
187:
188: String msg;
189: msg = "readLimit=" + readLimit + " writeLimit=" + writeLimit
190: + " minSleeps=" + minSleeps + " maxSleeps=" + maxSleeps
191: + " actualSleeps=" + nSleeps;
192: //System.out.println(msg);
193:
194: //*
195: assertTrue(msg, nSleeps >= minSleeps && nSleeps <= maxSleeps);
196: //*/
197: }
198:
199: /**
200: * Outputs an integer followed by pad bytes.
201: */
202: private void setKey(DatabaseEntry entry, int val, int len) {
203: TupleOutput out = new TupleOutput();
204: out.writeInt(val);
205: for (int i = 0; i < len - 4; i += 1) {
206: out.writeByte(0);
207: }
208: TupleBase.outputToEntry(out, entry);
209: }
210: }
|