001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: LogBufferPoolTest.java,v 1.59.2.3 2008/01/07 15:14:29 cwl Exp $
007: */
008:
009: package com.sleepycat.je.log;
010:
011: import java.io.File;
012: import java.io.IOException;
013: import java.io.RandomAccessFile;
014: import java.nio.ByteBuffer;
015: import java.nio.channels.FileChannel;
016: import java.util.ArrayList;
017: import java.util.Arrays;
018: import java.util.List;
019:
020: import junit.framework.TestCase;
021:
022: import com.sleepycat.je.Database;
023: import com.sleepycat.je.DatabaseConfig;
024: import com.sleepycat.je.DatabaseEntry;
025: import com.sleepycat.je.DatabaseException;
026: import com.sleepycat.je.DbInternal;
027: import com.sleepycat.je.Environment;
028: import com.sleepycat.je.EnvironmentConfig;
029: import com.sleepycat.je.config.EnvironmentParams;
030: import com.sleepycat.je.dbi.EnvironmentImpl;
031: import com.sleepycat.je.dbi.MemoryBudget;
032: import com.sleepycat.je.utilint.DbLsn;
033: import com.sleepycat.je.util.TestUtils;
034:
035: public class LogBufferPoolTest extends TestCase {
036:
037: Environment env;
038: Database db;
039: EnvironmentImpl environment;
040: FileManager fileManager;
041: File envHome;
042: LogBufferPool bufPool;
043:
044: public LogBufferPoolTest() {
045: super ();
046: envHome = new File(System.getProperty(TestUtils.DEST_DIR));
047: }
048:
049: protected void setUp() throws Exception {
050:
051: /* Remove files to start with a clean slate. */
052: TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX);
053: }
054:
055: protected void tearDown() throws Exception {
056:
057: bufPool = null;
058: if (fileManager != null) {
059: fileManager.clear();
060: fileManager.close();
061: }
062: TestUtils.removeFiles("TearDown", envHome,
063: FileManager.JE_SUFFIX);
064: }
065:
066: /**
067: * Make sure that we'll add more buffers as needed.
068: */
069: public void testGrowBuffers() throws Throwable {
070:
071: try {
072:
073: setupEnv(true);
074:
075: /*
076: * Each buffer can only hold 2 items. Put enough test items in to
077: * get seven buffers.
078: */
079: List lsns = new ArrayList();
080: for (int i = 0; i < 14; i++) {
081: long lsn = insertData(bufPool, (byte) (i + 1));
082: lsns.add(new Long(lsn));
083: }
084:
085: /*
086: * Check that the bufPool knows where each LSN lives and that the
087: * fetched buffer does hold this item.
088: */
089: LogBuffer logBuf;
090: ByteBuffer b;
091: for (int i = 0; i < 14; i++) {
092:
093: /*
094: * For each test LSN, ask the bufpool for the logbuffer that
095: * houses it.
096: */
097: long testLsn = DbLsn.longToLsn((Long) lsns.get(i));
098: logBuf = bufPool.getReadBuffer(testLsn);
099: assertNotNull(logBuf);
100:
101: /* Here's the expected data. */
102: byte[] expected = new byte[10];
103: Arrays.fill(expected, (byte) (i + 1));
104:
105: /* Here's the data in the log buffer. */
106: byte[] logData = new byte[10];
107: b = logBuf.getDataBuffer();
108: long firstLsnInBuf = logBuf.getFirstLsn();
109: b.position((int) (DbLsn.getFileOffset(testLsn) - DbLsn
110: .getFileOffset(firstLsnInBuf)));
111: logBuf.getDataBuffer().get(logData);
112:
113: /* They'd better be equal. */
114: assertTrue(Arrays.equals(logData, expected));
115: logBuf.release();
116: }
117:
118: /*
119: * This LSN shouldn't be in the buffers, it's less than any
120: * buffered item.
121: */
122: assertNull(bufPool.getReadBuffer(DbLsn.makeLsn(0, 10)));
123:
124: /*
125: * This LSN is illegal to ask for, it's greater than any registered
126: * LSN.
127: */
128: assertNull("LSN too big", bufPool.getReadBuffer(DbLsn
129: .makeLsn(10, 141)));
130: } catch (Throwable t) {
131: t.printStackTrace();
132: throw t;
133: }
134: }
135:
136: /**
137: * Helper to insert fake data.
138: * @return LSN registered for this fake data
139: */
140: private long insertData(LogBufferPool bufPool, byte value)
141: throws IOException, DatabaseException {
142:
143: byte[] data = new byte[10];
144: Arrays.fill(data, value);
145: boolean flippedFile = fileManager.bumpLsn(data.length);
146: LogBuffer logBuf = bufPool.getWriteBuffer(data.length,
147: flippedFile);
148: logBuf.getDataBuffer().put(data);
149: long lsn = fileManager.getLastUsedLsn();
150: bufPool.writeCompleted(fileManager.getLastUsedLsn(), false);
151: return lsn;
152: }
153:
154: /**
155: * Test buffer flushes.
156: */
157: public void testBufferFlush() throws Throwable {
158:
159: try {
160: setupEnv(false);
161: assertFalse("There should be no files", fileManager
162: .filesExist());
163:
164: /*
165: * Each buffer can only hold 2 items. Put enough test items in to
166: * get five buffers.
167: */
168: /* CWL: What is lsnList used for? */
169: List lsnList = new ArrayList();
170: for (int i = 0; i < 9; i++) {
171: long lsn = insertData(bufPool, (byte) (i + 1));
172: lsnList.add(new Long(lsn));
173: }
174: bufPool.writeBufferToFile(0);
175: fileManager.syncLogEnd();
176:
177: /* We should see two files exist. */
178: String[] fileNames = fileManager
179: .listFiles(FileManager.JE_SUFFIXES);
180: assertEquals("Should be 2 files", 2, fileNames.length);
181:
182: /* Read the files. */
183: if (false) {
184: ByteBuffer dataBuffer = ByteBuffer.allocate(100);
185: FileHandle file0 = fileManager.getFileHandle(0L);
186: RandomAccessFile file = file0.getFile();
187: FileChannel channel = file.getChannel();
188: int bytesRead = channel.read(dataBuffer, FileManager
189: .firstLogEntryOffset());
190: dataBuffer.flip();
191: assertEquals("Check bytes read", 50, bytesRead);
192: assertEquals("Check size of file", 50, dataBuffer
193: .limit());
194: file.close();
195: FileHandle file1 = fileManager.getFileHandle(1L);
196: file = file1.getFile();
197: channel = file.getChannel();
198: bytesRead = channel.read(dataBuffer, FileManager
199: .firstLogEntryOffset());
200: dataBuffer.flip();
201: assertEquals("Check bytes read", 40, bytesRead);
202: assertEquals("Check size of file", 40, dataBuffer
203: .limit());
204: file0.release();
205: file1.release();
206: }
207: } catch (Throwable e) {
208: e.printStackTrace();
209: throw e;
210: }
211: }
212:
213: public void testTemporaryBuffers() throws Exception {
214:
215: final int KEY_SIZE = 10;
216: final int DATA_SIZE = 1000000;
217:
218: tempBufferInitEnvInternal("0",
219: MemoryBudget.MIN_MAX_MEMORY_SIZE_STRING);
220: DatabaseEntry key = new DatabaseEntry(new byte[KEY_SIZE]);
221: DatabaseEntry data = new DatabaseEntry(new byte[DATA_SIZE]);
222: db.put(null, key, data);
223: db.close();
224: env.close();
225: }
226:
227: private void tempBufferInitEnvInternal(String buffSize,
228: String cacheSize) throws DatabaseException {
229:
230: EnvironmentConfig envConfig = TestUtils.initEnvConfig();
231: envConfig.setTransactional(true);
232: envConfig.setAllowCreate(true);
233: if (!buffSize.equals("0")) {
234: envConfig.setConfigParam("je.log.totalBufferBytes",
235: buffSize);
236: }
237:
238: if (!cacheSize.equals("0")) {
239: envConfig.setConfigParam("je.maxMemory", cacheSize);
240: }
241: env = new Environment(envHome, envConfig);
242:
243: DatabaseConfig dbConfig = new DatabaseConfig();
244: dbConfig.setAllowCreate(true);
245: dbConfig.setSortedDuplicates(true);
246: dbConfig.setTransactional(true);
247: db = env.openDatabase(null, "InsertAndDelete", dbConfig);
248: }
249:
250: private void setupEnv(boolean inMemory) throws Exception {
251:
252: EnvironmentConfig envConfig = TestUtils.initEnvConfig();
253:
254: DbInternal.disableParameterValidation(envConfig);
255: envConfig.setConfigParam(EnvironmentParams.LOG_MEM_SIZE
256: .getName(), EnvironmentParams.LOG_MEM_SIZE_MIN_STRING);
257: envConfig.setConfigParam(EnvironmentParams.LOG_FILE_MAX
258: .getName(), "90");
259: envConfig.setConfigParam(EnvironmentParams.NUM_LOG_BUFFERS
260: .getName(), "2");
261: envConfig.setAllowCreate(true);
262: if (inMemory) {
263: /* Make the bufPool grow some buffers. Disable writing. */
264: envConfig.setConfigParam(EnvironmentParams.LOG_MEMORY_ONLY
265: .getName(), "true");
266: }
267: environment = new EnvironmentImpl(envHome, envConfig);
268:
269: /* Make a standalone file manager for this test. */
270: environment.close();
271: environment.open(); /* Just sets state to OPEN. */
272: fileManager = new FileManager(environment, envHome, false);
273: bufPool = new LogBufferPool(fileManager, environment);
274:
275: /*
276: * Remove any files after the environment is created again! We want to
277: * remove the files made by recovery, so we can test the file manager
278: * in controlled cases.
279: */
280: TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX);
281: }
282: }
|