001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: LoggableTest.java,v 1.81.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.nio.ByteBuffer;
014:
015: import javax.xml.parsers.DocumentBuilderFactory;
016:
017: import junit.framework.TestCase;
018:
019: import com.sleepycat.je.DatabaseConfig;
020: import com.sleepycat.je.DatabaseException;
021: import com.sleepycat.je.EnvironmentConfig;
022: import com.sleepycat.je.cleaner.FileSummary;
023: import com.sleepycat.je.config.EnvironmentParams;
024: import com.sleepycat.je.dbi.DatabaseId;
025: import com.sleepycat.je.dbi.DatabaseImpl;
026: import com.sleepycat.je.dbi.DbTree;
027: import com.sleepycat.je.dbi.EnvironmentImpl;
028: import com.sleepycat.je.recovery.CheckpointEnd;
029: import com.sleepycat.je.recovery.CheckpointStart;
030: import com.sleepycat.je.tree.BIN;
031: import com.sleepycat.je.tree.ChildReference;
032: import com.sleepycat.je.tree.DBIN;
033: import com.sleepycat.je.tree.DIN;
034: import com.sleepycat.je.tree.FileSummaryLN;
035: import com.sleepycat.je.tree.IN;
036: import com.sleepycat.je.tree.INDeleteInfo;
037: import com.sleepycat.je.tree.LN;
038: import com.sleepycat.je.tree.MapLN;
039: import com.sleepycat.je.tree.Node;
040: import com.sleepycat.je.txn.TxnAbort;
041: import com.sleepycat.je.txn.TxnCommit;
042: import com.sleepycat.je.txn.TxnPrepare;
043: import com.sleepycat.je.util.TestUtils;
044: import com.sleepycat.je.utilint.DbLsn;
045: import com.sleepycat.je.utilint.Tracer;
046:
047: /**
048: * Check that every loggable object can be read in and out of a buffer
049: */
050: public class LoggableTest extends TestCase {
051:
052: static private final boolean DEBUG = false;
053:
054: // private DocumentBuilder builder;
055: private EnvironmentImpl env;
056: private File envHome;
057: private DatabaseImpl database;
058:
059: public LoggableTest() throws Exception {
060:
061: envHome = new File(System.getProperty(TestUtils.DEST_DIR));
062:
063: /*
064: * Attempt to validate that the db print log output is valid
065: * xml -- isn't quite working
066: */
067: DocumentBuilderFactory factory = DocumentBuilderFactory
068: .newInstance();
069: }
070:
071: public void setUp() throws IOException, DatabaseException {
072:
073: TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX);
074:
075: EnvironmentConfig envConfig = TestUtils.initEnvConfig();
076: envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(),
077: "6");
078: envConfig.setAllowCreate(true);
079: env = new EnvironmentImpl(envHome, envConfig);
080: }
081:
082: public void tearDown() throws IOException, DatabaseException {
083:
084: TestUtils.removeFiles("TearDown", envHome,
085: FileManager.JE_SUFFIX);
086: env.close();
087: }
088:
089: public void testEntryData() throws Throwable {
090:
091: try {
092: ByteBuffer buffer = ByteBuffer.allocate(1000);
093: database = new DatabaseImpl("foo", new DatabaseId(1), env,
094: new DatabaseConfig());
095:
096: /*
097: * For each loggable object, can we write the entry data out?
098: */
099:
100: /*
101: * Tracer records.
102: */
103: Tracer dMsg = new Tracer("Hello there");
104: writeAndRead(buffer, LogEntryType.LOG_TRACE, dMsg,
105: new Tracer());
106:
107: /*
108: * LNs
109: */
110: String data = "abcdef";
111: LN ln = new LN(data.getBytes());
112: LN lnFromLog = new LN();
113: writeAndRead(buffer, LogEntryType.LOG_LN, ln, lnFromLog);
114: lnFromLog.verify(null);
115: assertTrue(LogEntryType.LOG_LN.marshallOutsideLatch());
116:
117: FileSummaryLN fsLN = new FileSummaryLN(new FileSummary());
118: FileSummaryLN fsLNFromLog = new FileSummaryLN();
119: writeAndRead(buffer, LogEntryType.LOG_FILESUMMARYLN, fsLN,
120: fsLNFromLog);
121: assertFalse(LogEntryType.LOG_FILESUMMARYLN
122: .marshallOutsideLatch());
123:
124: /*
125: * INs
126: */
127: IN in = new IN(database, new byte[] { 1, 0, 1, 0 }, 7, 5);
128: in.latch();
129: in.insertEntry(new ChildReference(null, new byte[] { 1, 0,
130: 1, 0 }, DbLsn.makeLsn(12, 200)));
131: in.insertEntry(new ChildReference(null, new byte[] { 1, 1,
132: 1, 0 }, DbLsn.makeLsn(29, 300)));
133: in.insertEntry(new ChildReference(null, new byte[] { 0, 0,
134: 1, 0 }, DbLsn.makeLsn(35, 400)));
135:
136: /* Write it. */
137: IN inFromLog = new IN();
138: inFromLog.latch();
139: writeAndRead(buffer, LogEntryType.LOG_IN, in, inFromLog);
140: inFromLog.releaseLatch();
141: in.releaseLatch();
142:
143: /*
144: * IN - long form
145: */
146: in = new IN(database, new byte[] { 1, 0, 1, 0 }, 7, 5);
147: in.latch();
148: in.insertEntry(new ChildReference(null, new byte[] { 1, 0,
149: 1, 0 }, DbLsn.makeLsn(12, 200)));
150: in.insertEntry(new ChildReference(null, new byte[] { 1, 1,
151: 1, 0 }, DbLsn.makeLsn(29, 300)));
152: in.insertEntry(new ChildReference(null, new byte[] { 0, 0,
153: 1, 0 }, DbLsn.makeLsn(1235, 400)));
154: in.insertEntry(new ChildReference(null, new byte[] { 0, 0,
155: 1, 0 }, DbLsn.makeLsn(0xFFFFFFF0L, 400)));
156:
157: /* Write it. */
158: inFromLog = new IN();
159: inFromLog.latch();
160: writeAndRead(buffer, LogEntryType.LOG_IN, in, inFromLog);
161: inFromLog.releaseLatch();
162: in.releaseLatch();
163:
164: /*
165: * BINs
166: */
167: BIN bin = new BIN(database, new byte[] { 3, 2, 1 }, 8, 5);
168: bin.latch();
169: bin.insertEntry(new ChildReference(null, new byte[] { 1, 0,
170: 1, 0 }, DbLsn.makeLsn(212, 200)));
171: bin.insertEntry(new ChildReference(null, new byte[] { 1, 1,
172: 1, 0 }, DbLsn.makeLsn(229, 300)));
173: bin.insertEntry(new ChildReference(null, new byte[] { 0, 0,
174: 1, 0 }, DbLsn.makeLsn(235, 400)));
175: BIN binFromLog = new BIN();
176: binFromLog.latch();
177: writeAndRead(buffer, LogEntryType.LOG_BIN, bin, binFromLog);
178: binFromLog.verify(null);
179: binFromLog.releaseLatch();
180: bin.releaseLatch();
181:
182: /*
183: * DINs
184: */
185: DIN din = new DIN(database, new byte[] { 1, 0, 0, 1 }, 7,
186: new byte[] { 0, 1, 1, 0 }, new ChildReference(null,
187: new byte[] { 1, 0, 0, 1 }, DbLsn.makeLsn(
188: 10, 100)), 5);
189: din.latch();
190: din.insertEntry(new ChildReference(null, new byte[] { 1, 0,
191: 1, 0 }, DbLsn.makeLsn(12, 200)));
192: din.insertEntry(new ChildReference(null, new byte[] { 1, 1,
193: 1, 0 }, DbLsn.makeLsn(29, 300)));
194: din.insertEntry(new ChildReference(null, new byte[] { 0, 0,
195: 1, 0 }, DbLsn.makeLsn(35, 400)));
196:
197: /* Write it. */
198: DIN dinFromLog = new DIN();
199: dinFromLog.latch();
200: writeAndRead(buffer, LogEntryType.LOG_DIN, din, dinFromLog);
201: din.releaseLatch();
202: dinFromLog.releaseLatch();
203:
204: /*
205: * DBINs
206: */
207: DBIN dbin = new DBIN(database, new byte[] { 3, 2, 1 }, 8,
208: new byte[] { 1, 2, 3 }, 5);
209: dbin.latch();
210: dbin.insertEntry(new ChildReference(null, new byte[] { 1,
211: 0, 1, 0 }, DbLsn.makeLsn(212, 200)));
212: dbin.insertEntry(new ChildReference(null, new byte[] { 1,
213: 1, 1, 0 }, DbLsn.makeLsn(229, 300)));
214: dbin.insertEntry(new ChildReference(null, new byte[] { 0,
215: 0, 1, 0 }, DbLsn.makeLsn(235, 400)));
216: DBIN dbinFromLog = new DBIN();
217: dbinFromLog.latch();
218: writeAndRead(buffer, LogEntryType.LOG_DBIN, dbin,
219: dbinFromLog);
220: dbinFromLog.verify(null);
221: dbin.releaseLatch();
222: dbinFromLog.releaseLatch();
223:
224: /*
225: * Root
226: */
227: DbTree dbTree = new DbTree(env);
228: DbTree dbTreeFromLog = new DbTree();
229: writeAndRead(buffer, LogEntryType.LOG_ROOT, dbTree,
230: dbTreeFromLog);
231:
232: /*
233: * MapLN
234: */
235: MapLN mapLn = new MapLN(database);
236: MapLN mapLnFromLog = new MapLN();
237: writeAndRead(buffer, LogEntryType.LOG_MAPLN, mapLn,
238: mapLnFromLog);
239:
240: /*
241: * UserTxn
242: */
243:
244: /*
245: * Disabled for now because these txns don't compare equal,
246: * because one has a name of "main" and the other has a name of
247: * null because it was read from the log.
248:
249: Txn txn = new Txn(env, new TransactionConfig());
250: Txn txnFromLog = new Txn();
251: writeAndRead(buffer, LogEntryType.TXN_COMMIT, txn, txnFromLog);
252: txn.commit();
253: */
254:
255: /*
256: * TxnCommit
257: */
258: TxnCommit commit = new TxnCommit(111, DbLsn.makeLsn(10, 10));
259: TxnCommit commitFromLog = new TxnCommit();
260: writeAndRead(buffer, LogEntryType.LOG_TXN_COMMIT, commit,
261: commitFromLog);
262:
263: /*
264: * TxnAbort
265: */
266: TxnAbort abort = new TxnAbort(111, DbLsn.makeLsn(11, 11));
267: TxnAbort abortFromLog = new TxnAbort();
268: writeAndRead(buffer, LogEntryType.LOG_TXN_ABORT, abort,
269: abortFromLog);
270:
271: /*
272: * TxnPrepare
273: */
274: byte[] gid = new byte[64];
275: byte[] bqual = new byte[64];
276: TxnPrepare prepare = new TxnPrepare(111,
277: new LogUtils.XidImpl(1, gid, bqual));
278: TxnPrepare prepareFromLog = new TxnPrepare();
279: writeAndRead(buffer, LogEntryType.LOG_TXN_PREPARE, prepare,
280: prepareFromLog);
281:
282: prepare = new TxnPrepare(111, new LogUtils.XidImpl(1, null,
283: bqual));
284: prepareFromLog = new TxnPrepare();
285: writeAndRead(buffer, LogEntryType.LOG_TXN_PREPARE, prepare,
286: prepareFromLog);
287:
288: prepare = new TxnPrepare(111, new LogUtils.XidImpl(1, gid,
289: null));
290: prepareFromLog = new TxnPrepare();
291: writeAndRead(buffer, LogEntryType.LOG_TXN_PREPARE, prepare,
292: prepareFromLog);
293:
294: /*
295: * IN delete info
296: */
297: INDeleteInfo info = new INDeleteInfo(77, new byte[1],
298: new DatabaseId(100));
299: INDeleteInfo infoFromLog = new INDeleteInfo();
300: writeAndRead(buffer, LogEntryType.LOG_IN_DELETE_INFO, info,
301: infoFromLog);
302:
303: /*
304: * Checkpoint start
305: */
306: CheckpointStart start = new CheckpointStart(177, "test");
307: CheckpointStart startFromLog = new CheckpointStart();
308: writeAndRead(buffer, LogEntryType.LOG_CKPT_START, start,
309: startFromLog);
310:
311: /*
312: * Checkpoint end
313: */
314: CheckpointEnd end = new CheckpointEnd("test", DbLsn
315: .makeLsn(20, 55), env.getRootLsn(), env
316: .getTxnManager().getFirstActiveLsn(), Node
317: .getLastId(), env.getDbMapTree().getLastDbId(), env
318: .getTxnManager().getLastTxnId(), 177);
319: CheckpointEnd endFromLog = new CheckpointEnd();
320: writeAndRead(buffer, LogEntryType.LOG_CKPT_END, end,
321: endFromLog);
322: } catch (Throwable t) {
323: t.printStackTrace();
324: throw t;
325: }
326: }
327:
328: /**
329: * Helper which takes a dbLoggable, writes it, reads it back and
330: * checks for equality and size
331: */
332: private void writeAndRead(ByteBuffer buffer,
333: LogEntryType entryType, Loggable orig, Loggable fromLog)
334: throws Exception {
335:
336: byte entryTypeVersion = entryType.getVersion();
337:
338: /* Write it. */
339: buffer.clear();
340: orig.writeToLog(buffer);
341:
342: /* Check the log size. */
343: buffer.flip();
344: assertEquals(buffer.limit(), orig.getLogSize());
345:
346: /*
347: * Read it and compare sizes. Note that we assume we're testing
348: * objects that are readable and writable to the log.
349: */
350: fromLog.readFromLog(buffer, entryTypeVersion);
351: assertEquals(orig.getLogSize(), fromLog.getLogSize());
352:
353: assertEquals("We should have read the whole buffer for "
354: + fromLog.getClass().getName(), buffer.limit(), buffer
355: .position());
356:
357: /* Compare contents. */
358: StringBuffer sb1 = new StringBuffer();
359: StringBuffer sb2 = new StringBuffer();
360: orig.dumpLog(sb1, true);
361: fromLog.dumpLog(sb2, true);
362:
363: if (DEBUG) {
364: System.out.println("sb1 = " + sb1.toString());
365: System.out.println("sb2 = " + sb2.toString());
366: }
367: assertEquals("Not equals for " + fromLog.getClass().getName(),
368: sb1.toString(), sb2.toString());
369:
370: /* Validate that the dump string is valid XML. */
371: // builder = factory.newDocumentBuilder();
372: // builder.parse("<?xml version=\"1.0\" ?>");
373: // sb1.toString()+
374: }
375: }
|