1 8 9 package com.sleepycat.je.test; 10 11 import junit.framework.Test; 12 13 import com.sleepycat.je.Database; 14 import com.sleepycat.je.DatabaseConfig; 15 import com.sleepycat.je.DatabaseEntry; 16 import com.sleepycat.je.DatabaseException; 17 import com.sleepycat.je.LockMode; 18 import com.sleepycat.je.OperationStatus; 19 import com.sleepycat.je.SecondaryConfig; 20 import com.sleepycat.je.SecondaryCursor; 21 import com.sleepycat.je.SecondaryDatabase; 22 import com.sleepycat.je.SecondaryKeyCreator; 23 import com.sleepycat.je.Transaction; 24 import com.sleepycat.je.junit.JUnitMethodThread; 25 import com.sleepycat.je.util.TestUtils; 26 27 46 public class SecondaryDirtyReadTest extends MultiKeyTxnTestCase { 47 48 private static final int MAX_KEY = 1000; 49 50 public static Test suite() { 51 return multiKeyTxnTestSuite(SecondaryDirtyReadTest.class, null, 52 null); 53 } 55 56 private int nextKey; 57 private Database priDb; 58 private SecondaryDatabase secDb; 59 private LockMode lockMode = LockMode.READ_UNCOMMITTED; 60 61 64 public void tearDown() 65 throws Exception { 66 67 if (secDb != null) { 68 try { 69 secDb.close(); 70 } catch (Exception e) {} 71 secDb = null; 72 } 73 if (priDb != null) { 74 try { 75 priDb.close(); 76 } catch (Exception e) {} 77 priDb = null; 78 } 79 super.tearDown(); 80 } 81 82 86 public void testDeleteWhileReadingByKey() 87 throws Throwable { 88 89 doTest("runReadUncommittedByKey", "runPrimaryDelete"); 90 } 91 92 98 public void testDeleteWhileScanning() 99 throws Throwable { 100 101 doTest("runReadUncommittedScan", "runPrimaryDelete"); 102 } 103 104 109 public void testUpdateWhileReadingByKey() 110 throws Throwable { 111 112 doTest("runReadUncommittedByKey", "runPrimaryUpdate"); 113 } 114 115 118 public void testUpdateWhileScanning() 119 throws Throwable { 120 121 doTest("runReadUncommittedScan", "runPrimaryUpdate"); 122 } 123 124 128 public void doTest(String method1, String method2) 129 throws Throwable { 130 131 JUnitMethodThread tester1 = new JUnitMethodThread(method1 + "-t1", 132 method1, this); 133 JUnitMethodThread tester2 = new JUnitMethodThread(method2 + "-t2", 134 method2, this); 135 priDb = openPrimary("testDB"); 136 secDb = openSecondary(priDb, "testSecDB", false); 137 addRecords(); 138 tester1.start(); 139 tester2.start(); 140 tester1.finishTest(); 141 tester2.finishTest(); 142 secDb.close(); 143 secDb = null; 144 priDb.close(); 145 priDb = null; 146 } 147 148 151 public void runPrimaryDelete() 152 throws DatabaseException { 153 154 DatabaseEntry key = new DatabaseEntry(); 155 while (nextKey < MAX_KEY - 1) { 156 Transaction txn = txnBegin(); 157 key.setData(TestUtils.getTestArray(nextKey)); 158 OperationStatus status = priDb.delete(txn, key); 159 if (status != OperationStatus.SUCCESS) { 160 assertEquals(OperationStatus.NOTFOUND, status); 161 } 162 txnCommit(txn); 163 } 164 } 165 166 171 public void runPrimaryUpdate() 172 throws DatabaseException { 173 174 DatabaseEntry key = new DatabaseEntry(); 175 DatabaseEntry data = new DatabaseEntry(); 176 while (nextKey < MAX_KEY - 1) { 177 Transaction txn = txnBegin(); 178 key.setData(TestUtils.getTestArray(nextKey)); 179 data.setData(TestUtils.getTestArray(-1)); 180 OperationStatus status = priDb.put(txn, key, data); 181 assertEquals(OperationStatus.SUCCESS, status); 182 txnCommit(txn); 183 } 184 } 185 186 191 public void runReadUncommittedByKey() 192 throws DatabaseException { 193 194 DatabaseEntry key = new DatabaseEntry(); 195 DatabaseEntry pKey = new DatabaseEntry(); 196 DatabaseEntry data = new DatabaseEntry(); 197 while (nextKey < MAX_KEY - 1) { 198 key.setData(TestUtils.getTestArray(nextKey)); 199 OperationStatus status = secDb.get(null, key, pKey, data, 200 lockMode); 201 if (status != OperationStatus.SUCCESS) { 202 assertEquals(OperationStatus.NOTFOUND, status); 203 nextKey++; 204 } else { 205 assertEquals(nextKey, TestUtils.getTestVal(key.getData())); 206 assertEquals(nextKey, TestUtils.getTestVal(pKey.getData())); 207 assertEquals(nextKey, TestUtils.getTestVal(data.getData())); 208 } 209 } 210 } 211 212 218 public void runReadUncommittedScan() 219 throws DatabaseException { 220 221 DatabaseEntry key = new DatabaseEntry(); 222 DatabaseEntry pKey = new DatabaseEntry(); 223 DatabaseEntry data = new DatabaseEntry(); 224 SecondaryCursor cursor = secDb.openSecondaryCursor(null, null); 225 while (nextKey < MAX_KEY - 1) { 226 OperationStatus status = cursor.getNext(key, pKey, data, 227 lockMode); 228 assertEquals("nextKey=" + nextKey, 229 OperationStatus.SUCCESS, status); 230 int keyFound = TestUtils.getTestVal(key.getData()); 231 assertEquals(keyFound, TestUtils.getTestVal(pKey.getData())); 232 assertEquals(keyFound, TestUtils.getTestVal(data.getData())); 233 234 nextKey = keyFound; 235 if (nextKey < MAX_KEY - 1) { 236 while (status != OperationStatus.KEYEMPTY) { 237 assertEquals(OperationStatus.SUCCESS, status); 238 status = cursor.getCurrent(key, pKey, data, 239 lockMode); 240 } 241 nextKey = keyFound + 1; 242 } 243 } 244 cursor.close(); 245 } 246 247 250 private void addRecords() 251 throws DatabaseException { 252 253 DatabaseEntry key = new DatabaseEntry(); 254 DatabaseEntry data = new DatabaseEntry(); 255 Transaction txn = txnBegin(); 256 for (int i = 0; i < MAX_KEY; i += 1) { 257 byte[] val = TestUtils.getTestArray(i); 258 key.setData(val); 259 data.setData(val); 260 OperationStatus status = priDb.putNoOverwrite(txn, key, data); 261 assertEquals(OperationStatus.SUCCESS, status); 262 } 263 txnCommit(txn); 264 } 265 266 269 private Database openPrimary(String name) 270 throws DatabaseException { 271 272 DatabaseConfig dbConfig = new DatabaseConfig(); 273 dbConfig.setTransactional(isTransactional); 274 dbConfig.setAllowCreate(true); 275 Transaction txn = txnBegin(); 276 Database priDb; 277 try { 278 priDb = env.openDatabase(txn, name, dbConfig); 279 } finally { 280 txnCommit(txn); 281 } 282 assertNotNull(priDb); 283 return priDb; 284 } 285 286 289 private SecondaryDatabase openSecondary(Database priDb, String dbName, 290 boolean allowDuplicates) 291 throws DatabaseException { 292 293 SecondaryConfig dbConfig = new SecondaryConfig(); 294 dbConfig.setTransactional(isTransactional); 295 dbConfig.setAllowCreate(true); 296 dbConfig.setSortedDuplicates(allowDuplicates); 297 if (useMultiKey) { 298 dbConfig.setMultiKeyCreator 299 (new SimpleMultiKeyCreator(new MyKeyCreator())); 300 } else { 301 dbConfig.setKeyCreator(new MyKeyCreator()); 302 } 303 Transaction txn = txnBegin(); 304 SecondaryDatabase secDb; 305 try { 306 secDb = env.openSecondaryDatabase(txn, dbName, priDb, dbConfig); 307 } finally { 308 txnCommit(txn); 309 } 310 return secDb; 311 } 312 313 316 private static class MyKeyCreator implements SecondaryKeyCreator { 317 318 public boolean createSecondaryKey(SecondaryDatabase secondary, 319 DatabaseEntry key, 320 DatabaseEntry data, 321 DatabaseEntry result) 322 throws DatabaseException { 323 324 int val = TestUtils.getTestVal(data.getData()); 325 if (val >= 0) { 326 result.setData(TestUtils.getTestArray(val)); 327 return true; 328 } else { 329 return false; 330 } 331 } 332 } 333 } 334 | Popular Tags |