KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > txn > TxnMemoryTest


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

8
9 package com.sleepycat.je.txn;
10
11 import java.io.File JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.util.Enumeration JavaDoc;
14
15 import junit.framework.Test;
16 import junit.framework.TestCase;
17 import junit.framework.TestSuite;
18
19 import com.sleepycat.bind.tuple.IntegerBinding;
20 import com.sleepycat.je.Cursor;
21 import com.sleepycat.je.Database;
22 import com.sleepycat.je.DatabaseConfig;
23 import com.sleepycat.je.DatabaseEntry;
24 import com.sleepycat.je.DatabaseException;
25 import com.sleepycat.je.DbInternal;
26 import com.sleepycat.je.Environment;
27 import com.sleepycat.je.EnvironmentConfig;
28 import com.sleepycat.je.OperationStatus;
29 import com.sleepycat.je.Transaction;
30 import com.sleepycat.je.config.EnvironmentParams;
31 import com.sleepycat.je.dbi.EnvironmentImpl;
32 import com.sleepycat.je.dbi.MemoryBudget;
33 import com.sleepycat.je.log.FileManager;
34 import com.sleepycat.je.tree.IN;
35 import com.sleepycat.je.tree.LN;
36 import com.sleepycat.je.txn.Txn;
37 import com.sleepycat.je.util.TestUtils;
38
39 public class TxnMemoryTest extends TestCase {
40     private static final boolean DEBUG = false;
41     private static final String JavaDoc DB_NAME = "foo";
42
43     private static final String JavaDoc LOCK_AUTOTXN = "lock-autotxn";
44     private static final String JavaDoc LOCK_USERTXN = "lock-usertxn";
45     private static final String JavaDoc LOCK_NOTXN = "lock-notxn";
46     private static final String JavaDoc[] LOCK_MODE = {LOCK_AUTOTXN,
47                                                LOCK_USERTXN,
48                                                LOCK_NOTXN};
49     private static final String JavaDoc COMMIT = "commit";
50     private static final String JavaDoc ABORT = "abort";
51     private static final String JavaDoc [] END_MODE = {COMMIT, ABORT};
52
53     private File JavaDoc envHome;
54     private Environment env;
55     private EnvironmentImpl envImpl;
56     private MemoryBudget mb;
57     private Database db;
58     private DatabaseEntry keyEntry = new DatabaseEntry();
59     private DatabaseEntry dataEntry = new DatabaseEntry();
60     private String JavaDoc lockMode;
61     private String JavaDoc endMode;
62
63     private long beforeAction;
64     private long afterTxnsCreated;
65     private long afterAction;
66     private Transaction [] txns;
67     
68     private int numTxns = 2;
69     private int numRecordsPerTxn = 30;
70     
71     public static Test suite() {
72         TestSuite allTests = new TestSuite();
73         for (int i = 0; i < LOCK_MODE.length; i += 1) {
74             for (int eMode = 0; eMode < END_MODE.length; eMode ++) {
75                 TestSuite suite = new TestSuite(TxnMemoryTest.class);
76                 Enumeration JavaDoc e = suite.tests();
77                 while (e.hasMoreElements()) {
78                     TxnMemoryTest test = (TxnMemoryTest) e.nextElement();
79                     test.init(LOCK_MODE[i], END_MODE[eMode]);
80                     allTests.addTest(test);
81                 }
82             }
83         }
84         return allTests;
85     }
86
87     public TxnMemoryTest() {
88         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
89     }
90
91     private void init(String JavaDoc lockMode, String JavaDoc endMode) {
92         this.lockMode = lockMode;
93         this.endMode = endMode;
94     }
95
96     public void setUp()
97         throws IOException JavaDoc, DatabaseException {
98
99     IN.ACCUMULATED_LIMIT = 0;
100     Txn.ACCUMULATED_LIMIT = 0;
101
102         TestUtils.removeLogFiles("Setup", envHome, false);
103         TestUtils.removeFiles("Setup", envHome, FileManager.DEL_SUFFIX);
104     }
105
106     public void tearDown()
107         throws IOException JavaDoc, DatabaseException {
108         
109         /* Set test name for reporting; cannot be done in the ctor or setUp. */
110         setName(lockMode + '/' + endMode + ":" + getName());
111
112         try {
113             if (env != null) {
114                 env.close();
115             }
116         } catch (Throwable JavaDoc e) {
117             System.out.println("tearDown: " + e);
118         }
119                 
120         try {
121             TestUtils.removeLogFiles("tearDown", envHome, true);
122             TestUtils.removeFiles("tearDown", envHome, FileManager.DEL_SUFFIX);
123         } catch (Throwable JavaDoc e) {
124             System.out.println("tearDown: " + e);
125         }
126
127         db = null;
128         env = null;
129     }
130
131     /**
132      * Opens the environment and database.
133      */

134     private void openEnv()
135         throws DatabaseException {
136
137         EnvironmentConfig config = TestUtils.initEnvConfig();
138
139         /*
140          * ReadCommitted isolation is not allowed by this test because we
141          * expect no locks/memory to be freed when using a transaction.
142          */

143         DbInternal.setTxnReadCommitted(config, false);
144
145         /* Cleaner detail tracking adds to the memory budget; disable it. */
146         config.setConfigParam
147             (EnvironmentParams.CLEANER_TRACK_DETAIL.getName(), "false");
148
149         config.setTransactional(true);
150         config.setAllowCreate(true);
151         env = new Environment(envHome, config);
152         envImpl = DbInternal.envGetEnvironmentImpl(env);
153         mb = envImpl.getMemoryBudget();
154
155         DatabaseConfig dbConfig = new DatabaseConfig();
156         dbConfig.setTransactional(!lockMode.equals(LOCK_NOTXN));
157         dbConfig.setAllowCreate(true);
158         db = env.openDatabase(null, DB_NAME, dbConfig);
159     }
160
161     /**
162      * Closes the environment and database.
163      */

164     private void closeEnv(boolean doCheckpoint)
165         throws DatabaseException {
166
167         if (db != null) {
168             db.close();
169             db = null;
170         }
171         if (env != null) {
172             env.close();
173             env = null;
174         }
175     }
176
177     /**
178      * Insert and then update some records. Measure memory usage at different
179      * points in this sequence, asserting that the memory usage count is
180      * properly decremented.
181      */

182     public void testWriteLocks()
183         throws DatabaseException {
184
185         loadData();
186
187
188         /*
189          * Now update the database transactionally. This should not change
190          * the node related memory, but should add txn related cache
191          * consumption. If this is a user transaction, we should
192          * hold locks and consume more memory.
193          */

194         for (int t = 0; t < numTxns; t++) {
195             for (int i = 0; i < numRecordsPerTxn; i++) {
196                 int value = i + (t*numRecordsPerTxn);
197                 IntegerBinding.intToEntry(value, keyEntry);
198                 IntegerBinding.intToEntry(value+1, dataEntry);
199                 assertEquals(db.put(txns[t], keyEntry, dataEntry),
200                              OperationStatus.SUCCESS);
201             }
202         }
203         afterAction = mb.getCacheMemoryUsage();
204
205         closeTxns(true);
206     }
207
208     /**
209      * Insert and then scan some records. Measure memory usage at different
210      * points in this sequence, asserting that the memory usage count is
211      * properly decremented.
212      */

213     public void testReadLocks()
214         throws DatabaseException {
215
216         loadData();
217
218         /*
219          * Now scan the database. Make sure all locking overhead is
220          * released.
221          */

222         for (int t = 0; t < numTxns; t++) {
223             Cursor c = db.openCursor(txns[t], null);
224             while (c.getNext(keyEntry, dataEntry, null) ==
225                    OperationStatus.SUCCESS) {
226             }
227             c.close();
228         }
229         afterAction = mb.getCacheMemoryUsage();
230
231         closeTxns(false);
232     }
233
234     private void loadData()
235         throws DatabaseException {
236
237         openEnv();
238
239         /* Build up a database to establish a given cache size. */
240         for (int t = 0; t < numTxns; t++) {
241             for (int i = 0; i < numRecordsPerTxn; i++) {
242
243                 int value = i + (t*numRecordsPerTxn);
244                 IntegerBinding.intToEntry(value, keyEntry);
245                 IntegerBinding.intToEntry(value, dataEntry);
246                 assertEquals(db.put(null, keyEntry, dataEntry),
247                              OperationStatus.SUCCESS);
248             }
249         }
250
251         beforeAction = mb.getCacheMemoryUsage();
252         
253         /* Make some transactions. */
254         txns = new Transaction[numTxns];
255         if (lockMode.equals(LOCK_USERTXN)) {
256             for (int t = 0; t < numTxns; t++) {
257                 txns[t] = env.beginTransaction(null, null);
258             }
259             
260             afterTxnsCreated = mb.getCacheMemoryUsage();
261             assertTrue( "afterTxns=" + afterTxnsCreated +
262                         "beforeUpdate=" + beforeAction,
263                         (afterTxnsCreated > beforeAction));
264         }
265     }
266
267     private void closeTxns(boolean writesDone)
268         throws DatabaseException {
269         
270     assertTrue(afterAction > afterTxnsCreated);
271
272         /*
273          * If this is not a user transactional lock, we should be done
274          * with all locking overhead. If it is a user transaction, we
275          * only release memory after locks are released at commit or
276          * abort.
277          */

278         if (lockMode.equals(LOCK_USERTXN)) {
279         
280             /*
281              * Note: expectedLockUsage is annoyingly fragile. If we change
282              * the lock implementation, this may not be the right number
283              * to check.
284              *
285              * Aborted transactions release more memory than just the lock
286              * related amount, because they actually null out LN references in
287              * the BINs.
288              */

289             long expectedLockUsage =
290                    (numRecordsPerTxn * numTxns *
291                     (LockManager.TOTAL_LOCK_OVERHEAD +
292                      MemoryBudget.LOCKINFO_OVERHEAD));
293
294             long expectedFreedNodeMemory = 0;
295
296             /*
297              * If this test aborted some writes, then there are rollbacks,
298              * which actually reduce the amount of memory held, because it
299              * causes LNs to get evicted.
300              */

301             if (endMode.equals(ABORT) &&
302                 writesDone) {
303                 LN sampleLN = new LN(dataEntry);
304                 expectedFreedNodeMemory +=
305                     ((numRecordsPerTxn * numTxns) *
306                      sampleLN.getMemorySizeIncludedByParent());
307             }
308
309             assertTrue((afterAction - afterTxnsCreated) >= expectedLockUsage);
310
311             for (int t = 0; t < numTxns; t++) {
312                 Transaction txn = txns[t];
313                 if (endMode.equals(COMMIT)) {
314                     txn.commit();
315                 } else {
316                     txn.abort();
317                 }
318             }
319
320             long afterTxnEnd = mb.getCacheMemoryUsage();
321
322             assertTrue("lockMode=" + lockMode +
323                " endMode=" + endMode +
324                " afterTxnEnd=" + afterTxnEnd +
325                " beforeAction=" + beforeAction +
326                " expectedFreed=" + expectedFreedNodeMemory,
327                (afterTxnEnd <=
328             (beforeAction - expectedFreedNodeMemory)));
329         }
330         if (DEBUG) {
331             System.out.println("afterUpdate = " + afterAction +
332                                " before=" + beforeAction);
333         }
334
335         closeEnv(true);
336     }
337 }
338
Popular Tags