KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > tree > BinDeltaTest


1 /*
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: BinDeltaTest.java,v 1.44 2006/10/30 21:14:51 bostic Exp $
7  */

8 package com.sleepycat.je.tree;
9
10 import java.io.File JavaDoc;
11 import java.io.IOException JavaDoc;
12
13 import junit.framework.TestCase;
14
15 import com.sleepycat.je.Cursor;
16 import com.sleepycat.je.Database;
17 import com.sleepycat.je.DatabaseConfig;
18 import com.sleepycat.je.DatabaseEntry;
19 import com.sleepycat.je.DatabaseException;
20 import com.sleepycat.je.DbInternal;
21 import com.sleepycat.je.Environment;
22 import com.sleepycat.je.EnvironmentConfig;
23 import com.sleepycat.je.LockMode;
24 import com.sleepycat.je.OperationStatus;
25 import com.sleepycat.je.Transaction;
26 import com.sleepycat.je.config.EnvironmentParams;
27 import com.sleepycat.je.dbi.CursorImpl;
28 import com.sleepycat.je.log.LogManager;
29 import com.sleepycat.je.log.FileManager;
30 import com.sleepycat.je.log.entry.LogEntry;
31 import com.sleepycat.je.txn.BasicLocker;
32 import com.sleepycat.je.txn.Locker;
33 import com.sleepycat.je.util.TestUtils;
34 import com.sleepycat.je.utilint.DbLsn;
35
36 /**
37  * Exercise the delta based BIN logging.
38  */

39 public class BinDeltaTest extends TestCase {
40     private static final String JavaDoc DB_NAME = "test";
41     private static final boolean DEBUG = false;
42     private Environment env;
43     private File JavaDoc envHome;
44     private Database db;
45     private LogManager logManager;
46
47     public BinDeltaTest() throws DatabaseException {
48         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
49
50         /* Print keys as numbers */
51         Key.DUMP_BINARY = true;
52     }
53
54     public void setUp() throws IOException JavaDoc, DatabaseException {
55         TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX);
56
57         /*
58          * Properties for creating an environment.
59          * Disable the evictor for this test, use larger BINS
60          */

61         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
62         envConfig.setTransactional(true);
63         envConfig.setConfigParam(EnvironmentParams.ENV_RUN_EVICTOR.getName(), "true");
64         envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(), "50");
65         envConfig.setConfigParam(EnvironmentParams.BIN_DELTA_PERCENT.getName(), "50");
66         envConfig.setAllowCreate(true);
67         env = new Environment(envHome, envConfig);
68         logManager = DbInternal.envGetEnvironmentImpl(env).getLogManager();
69     }
70
71     public void tearDown() throws IOException JavaDoc, DatabaseException {
72         if (env != null) {
73             try {
74                 env.close();
75             } catch (DatabaseException E) {
76             }
77         }
78         TestUtils.removeFiles("TearDown", envHome,
79                               FileManager.JE_SUFFIX, true);
80     }
81
82     /**
83      * Create a db, fill with numRecords, return the first BIN.
84      * @param numRecords
85      */

86     private BIN initDb(int start, int end)
87         throws DatabaseException {
88         DatabaseConfig dbConfig = new DatabaseConfig();
89         dbConfig.setTransactional(true);
90         dbConfig.setAllowCreate(true);
91         db = env.openDatabase(null, DB_NAME, dbConfig);
92
93         addRecords(start, end);
94
95         /* Now reach into the tree and get the first BIN */
96         Locker txn = new BasicLocker(DbInternal.envGetEnvironmentImpl(env));
97         CursorImpl internalCursor = new CursorImpl(DbInternal.dbGetDatabaseImpl(db),
98                            txn);
99         assertTrue(internalCursor.positionFirstOrLast(true, null));
100         BIN firstBIN = internalCursor.getBIN();
101         firstBIN.releaseLatch();
102         internalCursor.close();
103         txn.operationEnd();
104         return firstBIN;
105     }
106
107     /**
108      * Modify the data, just to dirty the BIN.
109      */

110     private void modifyRecords(int start, int end, int increment)
111         throws DatabaseException {
112
113         Transaction txn = env.beginTransaction(null, null);
114         Cursor cursor = db.openCursor(txn, null);
115         DatabaseEntry searchKey = new DatabaseEntry();
116         DatabaseEntry foundData = new DatabaseEntry();
117         DatabaseEntry newData = new DatabaseEntry();
118         
119         for (int i = start; i <= end; i++) {
120             searchKey.setData(TestUtils.getTestArray(i));
121             assertEquals(OperationStatus.SUCCESS,
122                          cursor.getSearchKey(searchKey, foundData,
123                                              LockMode.DEFAULT));
124             newData.setData(TestUtils.getTestArray(i+increment));
125             cursor.putCurrent(newData);
126         }
127     cursor.close();
128         txn.commit();
129     }
130
131     /*
132      * Add the specified records.
133      */

134     private void addRecords(int start, int end)
135         throws DatabaseException {
136
137         DatabaseEntry key = new DatabaseEntry();
138         DatabaseEntry data = new DatabaseEntry();
139         for (int i = start; i < end; i++) {
140             byte [] keyData = TestUtils.getTestArray(i);
141             byte [] dataData = TestUtils.byteArrayCopy(keyData);
142             key.setData(keyData);
143             data.setData(dataData);
144             db.put(null, key, data);
145         }
146     }
147     
148     /**
149      * Simple test, delta a BIN several times, reconstruct.
150      */

151     public void testSimple()
152         throws Throwable JavaDoc {
153
154         try {
155             /* Create a db, insert records value 10 - 30, get the first BIN */
156             BIN bin = initDb(10, 30);
157
158             /* Log a full version. */
159         bin.latch();
160             long fullLsn = bin.log
161                 (logManager, true, false, false, false, null);
162         bin.releaseLatch();
163             assertTrue(fullLsn != DbLsn.NULL_LSN);
164           
165             if (DEBUG) {
166                 System.out.println("Start");
167                 System.out.println(bin.dumpString(0, true));
168             }
169           
170             /* Modify some of the data, add data so the BIN is changed. */
171             modifyRecords(11,13,10);
172             addRecords(1,3);
173             logAndCheck(bin);
174
175             /* Modify more of the data, so the BIN is changed. */
176             modifyRecords(14,15,10);
177             logAndCheck(bin);
178         } catch (Throwable JavaDoc t) {
179             t.printStackTrace();
180             throw t;
181         } finally {
182             db.close();
183     }
184     }
185
186     /**
187      * Test that a delta is correctly generated when there are entries
188      * that have been aborted and rolled back.
189      *
190      * The case we're trying to test, (that was in error before)
191      * - a record is deleted
192      * - a full version of BIN x is written to the log, reflecting that
193      * deletion.
194      * - the deleting txn is aborted, so the record is restored. Now the
195      * BIN has an entry where the child LSN is less than the last full
196      * BIN version LSN.
197      * - generate a delta, make sure that the restoration of the record is
198      * present.
199      */

200     public void testUndo()
201         throws Throwable JavaDoc {
202
203         try {
204             /* Create a db, insert records value 10 - 30, get the first BIN */
205             BIN bin = initDb(10, 30);
206
207             /* Delete the first record, then abort the delete. */
208             Transaction txn = env.beginTransaction(null, null);
209             Cursor cursor = db.openCursor(txn, null);
210             DatabaseEntry firstKey = new DatabaseEntry();
211             DatabaseEntry foundData = new DatabaseEntry();
212             OperationStatus status = cursor.getFirst(firstKey, foundData,
213                              LockMode.DEFAULT);
214             assertEquals(OperationStatus.SUCCESS, status);
215             status = cursor.delete();
216             assertEquals(OperationStatus.SUCCESS, status);
217         cursor.close();
218
219             /* Log a full version. This will reflect the delete. */
220         bin.latch();
221             long fullLsn = bin.log
222                 (logManager, true, false, false, false, null);
223         bin.releaseLatch();
224             assertTrue(fullLsn != DbLsn.NULL_LSN);
225           
226             /*
227              * Roll back the deletion. Now the full version of the LSN is out
228              * of date.
229              */

230             txn.abort();
231
232             /*
233              * Make sure a delta reflect the abort, even though the abort
234              * returns an older LSN back into the BIN.
235              */

236             logAndCheck(bin);
237         } catch (Throwable JavaDoc t) {
238             t.printStackTrace();
239             throw t;
240         } finally {
241             db.close();
242         }
243     }
244
245     /* Check if full is logged when percent > max */
246     /* Check that max deltas works. */
247     /* check knownDelete. */
248
249     /**
250      * Log the targetBIN, then read it back from the log and make sure
251      * the recreated BIN matches the in memory BIN.
252      */

253     private void logAndCheck(BIN targetBIN)
254         throws DatabaseException {
255
256         /*
257          * Log it as a delta. If the logging was done as a delta, this method
258          * returns null, so we expect null
259          */

260         assertTrue(targetBIN.log
261                     (logManager, true, false, false, false, null) ==
262            DbLsn.NULL_LSN);
263
264         /* Read the delta back. */
265         LogEntry partial =
266             logManager.getLogEntry(targetBIN.getLastDeltaVersion());
267
268         /* Make sure that this is was a delta entry. */
269         assertTrue(partial.getMainItem() instanceof BINDelta);
270         BINDelta delta = (BINDelta) partial.getMainItem();
271
272         /* Compare to the current version. */
273         BIN createdBIN =
274             delta.reconstituteBIN(DbInternal.envGetEnvironmentImpl(env));
275         if (DEBUG) {
276             System.out.println("created");
277             System.out.println(createdBIN.dumpString(0, true));
278         }
279           
280         assertEquals(targetBIN.getClass().getName(),
281                      createdBIN.getClass().getName());
282         assertEquals(targetBIN.getNEntries(), createdBIN.getNEntries());
283         
284         for (int i = 0; i < createdBIN.getNEntries(); i++) {
285             assertEquals("LSN " + i, targetBIN.getLsn(i),
286                          createdBIN.getLsn(i));
287         }
288         assertEquals(true, createdBIN.getDirty());
289         assertEquals(true, targetBIN.getDirty());
290     }
291 }
292
Popular Tags