1 8 9 package com.sleepycat.je.tree; 10 11 import java.io.File ; 12 13 import junit.framework.TestCase; 14 15 import com.sleepycat.je.Database; 16 import com.sleepycat.je.DatabaseConfig; 17 import com.sleepycat.je.DatabaseException; 18 import com.sleepycat.je.DbInternal; 19 import com.sleepycat.je.Environment; 20 import com.sleepycat.je.EnvironmentConfig; 21 import com.sleepycat.je.OperationStatus; 22 import com.sleepycat.je.Transaction; 23 import com.sleepycat.je.config.EnvironmentParams; 24 import com.sleepycat.je.dbi.DatabaseImpl; 25 import com.sleepycat.je.latch.LatchSupport; 26 import com.sleepycat.je.util.StringDbt; 27 import com.sleepycat.je.util.TestUtils; 28 29 public class GetParentNodeTest extends TestCase { 30 static private final boolean DEBUG = false; 31 32 private File envHome; 33 private Environment env; 34 private Database db; 35 private IN rootIN; 36 private IN firstLevel2IN; 37 private BIN firstBIN; 38 private DBIN firstDBIN; 39 40 public GetParentNodeTest() { 41 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 42 } 43 44 public void setUp() 45 throws Exception { 46 TestUtils.removeLogFiles("Setup", envHome, false); 47 initEnv(); 48 } 49 50 public void tearDown() 51 throws Exception { 52 try { 53 db.close(); 54 env.close(); 55 } catch (DatabaseException E) { 56 } 57 58 TestUtils.removeLogFiles("TearDown", envHome, true); 59 } 60 61 private void initEnv() 62 throws DatabaseException { 63 64 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 65 envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(), "4"); 66 envConfig.setTransactional(true); 67 envConfig.setAllowCreate(true); 68 env = new Environment(envHome, envConfig); 69 70 String databaseName = "testDb"; 71 Transaction txn = env.beginTransaction(null, null); 72 DatabaseConfig dbConfig = new DatabaseConfig(); 73 dbConfig.setTransactional(true); 74 dbConfig.setAllowCreate(true); 75 dbConfig.setSortedDuplicates(true); 76 db = env.openDatabase(txn, databaseName, dbConfig); 77 txn.commit(); 78 } 79 80 84 public void testBasic() 85 throws Exception { 86 87 try { 88 107 assertEquals(OperationStatus.SUCCESS, 108 db.put(null, new StringDbt("a"), 109 new StringDbt("data1"))); 110 assertEquals(OperationStatus.SUCCESS, 111 db.put(null, new StringDbt("b"), 112 new StringDbt("data1"))); 113 assertEquals(OperationStatus.SUCCESS, 114 db.put(null, new StringDbt("c"), 115 new StringDbt("data1"))); 116 assertEquals(OperationStatus.SUCCESS, 117 db.put(null, new StringDbt("d"), 118 new StringDbt("data1"))); 119 assertEquals(OperationStatus.SUCCESS, 120 db.put(null, new StringDbt("e"), 121 new StringDbt("data1"))); 122 assertEquals(OperationStatus.SUCCESS, 123 db.put(null, new StringDbt("f"), 124 new StringDbt("data1"))); 125 assertEquals(OperationStatus.SUCCESS, 126 db.put(null, new StringDbt("g"), 127 new StringDbt("data1"))); 128 assertEquals(OperationStatus.SUCCESS, 129 db.put(null, new StringDbt("h"), 130 new StringDbt("data1"))); 131 assertEquals(OperationStatus.SUCCESS, 132 db.put(null, new StringDbt("i"), 133 new StringDbt("data1"))); 134 assertEquals(OperationStatus.SUCCESS, 135 db.put(null, new StringDbt("j"), 136 new StringDbt("data1"))); 137 assertEquals(OperationStatus.SUCCESS, 138 db.put(null, new StringDbt("k"), 139 new StringDbt("data1"))); 140 141 142 byte[] dupKey = "b".getBytes(); 143 assertEquals(OperationStatus.SUCCESS, 144 db.put(null, new StringDbt("b"), 145 new StringDbt("data2"))); 146 assertEquals(OperationStatus.SUCCESS, 147 db.put(null, new StringDbt("b"), 148 new StringDbt("data3"))); 149 assertEquals(OperationStatus.SUCCESS, 150 db.put(null, new StringDbt("b"), 151 new StringDbt("data4"))); 152 assertEquals(OperationStatus.SUCCESS, 153 db.put(null, new StringDbt("b"), 154 new StringDbt("data5"))); 155 assertEquals(OperationStatus.SUCCESS, 156 db.put(null, new StringDbt("b"), 157 new StringDbt("data6"))); 158 assertEquals(OperationStatus.SUCCESS, 159 db.put(null, new StringDbt("b"), 160 new StringDbt("data7"))); 161 162 165 checkTreeUsingExistingNodes(dupKey, true); 166 checkTreeUsingExistingNodes(dupKey, false); 167 168 169 checkTreeUsingPotentialNodes(); 170 171 172 checkTreeWithDeletedBins(true); 173 checkTreeWithDeletedBins(false); 174 175 176 assertEquals(0, LatchSupport.countLatchesHeld()); 177 } catch (Throwable t) { 178 t.printStackTrace(); 179 throw new Exception (t); 180 } 181 } 182 183 private void checkTreeUsingExistingNodes(byte[] dupKey, 184 boolean requireExactMatch) 185 throws DatabaseException { 186 187 188 DatabaseImpl database = DbInternal.dbGetDatabaseImpl(db); 189 Tree tree = database.getTree(); 190 191 if (DEBUG) { 192 tree.dump(); 193 } 194 195 rootIN = tree.withRootLatchedShared 196 (new GetRoot(DbInternal.dbGetDatabaseImpl(db))); 197 rootIN.latch(); 198 SearchResult result = tree.getParentINForChildIN(rootIN, true, true); 199 assertFalse(result.exactParentFound); 200 assertEquals(rootIN.getNEntries(), 2); 201 202 203 BIN dupTreeBin = null; 204 DIN dupTreeDINRoot = null; 205 firstBIN = null; 206 int dupIndex = -1; 207 for (int i = 0; i < rootIN.getNEntries(); i++) { 208 209 IN in = (IN) rootIN.fetchTarget(i); 210 if (i == 0) { 211 firstLevel2IN = in; 212 } 213 checkMatch(tree, in, rootIN, i, requireExactMatch); 214 215 216 for (int j = 0; j < in.getNEntries(); j++) { 217 BIN bin = (BIN) in.fetchTarget(j); 218 if (firstBIN == null) { 219 firstBIN = bin; 220 } 221 checkMatch(tree, bin, in, j, requireExactMatch); 222 223 for (int k = 0; k < bin.getNEntries(); k++) { 224 Node n = bin.fetchTarget(k); 225 if (n instanceof LN) { 226 checkMatch(tree, (LN) n, bin, bin.getKey(k), 227 null, k, bin.getLsn(k)); 228 } 229 } 230 231 int findIndex = bin.findEntry(dupKey, false, true); 232 if (findIndex > 0) { 233 dupIndex = findIndex; 234 dupTreeDINRoot = 235 (DIN) bin.fetchTarget(dupIndex); 236 dupTreeBin = bin; 237 } 238 } 239 } 240 241 242 assertTrue(dupTreeBin != null); 243 assertTrue(dupTreeDINRoot != null); 244 checkMatch(tree, dupTreeDINRoot, dupTreeBin, dupIndex, 245 requireExactMatch); 246 assertTrue(dupTreeDINRoot.getNEntries() > 0); 247 248 for (int i = 0; i < dupTreeDINRoot.getNEntries(); i++) { 249 IN in = (IN) dupTreeDINRoot.fetchTarget(i); 250 checkMatch(tree, in, dupTreeDINRoot, i, requireExactMatch); 251 if (firstDBIN == null) { 252 firstDBIN = (DBIN)in; 253 } 254 255 for (int k = 0; k < in.getNEntries(); k++) { 256 Node n = in.fetchTarget(k); 257 LN ln = (LN) n; 258 checkMatch(tree, ln, (BIN)in, dupKey, 259 ln.getData(), 260 k, in.getLsn(k)); 261 } 262 } 263 } 264 265 268 private void checkMatch(Tree tree, 269 IN target, 270 IN parent, 271 int index, 272 boolean requireExactMatch) 273 throws DatabaseException { 274 275 target.latch(); 276 SearchResult result = tree.getParentINForChildIN 277 (target, requireExactMatch, true); 278 assertTrue(result.exactParentFound); 279 assertEquals("Target=" + target + " parent=" + parent, 280 index, result.index); 281 assertEquals(parent, result.parent); 282 parent.releaseLatch(); 283 } 284 285 288 private void checkMatch(Tree tree, 289 LN target, 290 BIN parent, 291 byte[] mainKey, 292 byte[] dupKey, 293 int index, 294 long expectedLsn) 295 throws DatabaseException { 296 TreeLocation location = new TreeLocation(); 297 298 299 assertTrue 300 (tree.getParentBINForChildLN(location, mainKey, dupKey, target, 301 false, true, false, true)); 302 location.bin.releaseLatch(); 303 assertEquals(parent, location.bin); 304 assertEquals(index, location.index); 305 assertEquals(expectedLsn, location.childLsn); 306 307 assertTrue 308 (tree.getParentBINForChildLN(location, mainKey, dupKey, target, 309 true, false, true, true)); 310 location.bin.releaseLatch(); 311 assertEquals(parent, location.bin); 312 assertEquals(index, location.index); 313 assertEquals(expectedLsn, location.childLsn); 314 315 assertTrue 316 (tree.getParentBINForChildLN(location, mainKey, dupKey, target, 317 true, true, false, true)); 318 location.bin.releaseLatch(); 319 assertEquals(parent, location.bin); 320 assertEquals(index, location.index); 321 assertEquals(expectedLsn, location.childLsn); 322 } 323 324 private class GetRoot implements WithRootLatched { 325 326 private DatabaseImpl db; 327 328 GetRoot(DatabaseImpl db) { 329 this.db = db; 330 } 331 332 public IN doWork(ChildReference root) 333 throws DatabaseException { 334 335 return (IN) root.fetchTarget(db, null); 336 } 337 } 338 339 343 private void checkTreeUsingPotentialNodes() 344 throws DatabaseException { 345 346 DatabaseImpl database = DbInternal.dbGetDatabaseImpl(db); 347 Tree tree = database.getTree(); 348 349 353 IN inAB = new IN(database, "ab".getBytes(), 4, 2); 354 checkPotential(tree, inAB, firstLevel2IN); 355 356 360 BIN binAB = 361 new BIN(database, "ab".getBytes(), 4, 1); 362 checkPotential(tree, binAB, firstLevel2IN); 363 364 367 DIN dinA = new DIN(database, 368 "data1".getBytes(), 369 4, 370 "a".getBytes(), 371 null, 3); 372 checkPotential(tree, dinA, firstBIN); 373 374 378 LN LNab = new LN("foo".getBytes()); 379 byte[] mainKey = "ab".getBytes(); 380 checkPotential(tree, LNab, firstBIN, mainKey, 381 LNab.getData(), mainKey); 382 383 386 LN LNdata = new LN("data".getBytes()); 387 mainKey = "b".getBytes(); 388 byte[] dupKey = LNdata.getData(); 389 checkPotential(tree, LNdata, firstDBIN, mainKey, dupKey, dupKey); 390 } 391 392 private void checkPotential(Tree tree, IN potential, IN expectedParent) 393 throws DatabaseException { 394 395 396 potential.latch(); 397 SearchResult result = tree.getParentINForChildIN 398 (potential, true, true); 399 assertFalse(result.exactParentFound); 400 assertTrue(result.parent == null); 401 402 potential.latch(); 403 result = tree.getParentINForChildIN(potential, false, true); 404 assertFalse(result.exactParentFound); 405 assertEquals("expected = " + expectedParent.getNodeId() + 406 " got" + result.parent.getNodeId(), 407 expectedParent, result.parent); 408 result.parent.releaseLatch(); 409 } 410 411 private void checkPotential(Tree tree, LN potential, BIN expectedParent, 412 byte[] mainKey, byte[] dupKey, byte[] expectedKey) 413 throws DatabaseException { 414 415 416 TreeLocation location = new TreeLocation(); 417 assertFalse(tree.getParentBINForChildLN(location, 418 mainKey, dupKey, 419 potential, false, 420 false, true, true)); 421 location.bin.releaseLatch(); 422 assertEquals(location.bin, expectedParent); 423 assertEquals(expectedKey, location.lnKey); 424 } 425 426 private void checkTreeWithDeletedBins(boolean requireExactMatch) 427 throws DatabaseException { 428 429 433 DatabaseImpl database = DbInternal.dbGetDatabaseImpl(db); 434 Tree tree = database.getTree(); 435 436 rootIN = tree.withRootLatchedShared 437 (new GetRoot(DbInternal.dbGetDatabaseImpl(db))); 438 439 440 for (int i = 0; i < rootIN.getNEntries(); i++) { 441 442 IN in = (IN) rootIN.fetchTarget(i); 443 for (int j = 0; j < in.getNEntries(); j++) { 444 BIN bin = (BIN) in.getTarget(j); 445 in.setKnownDeleted(j); 446 checkDeletedMatch(tree, bin, in, j, requireExactMatch); 447 } 448 } 449 } 450 451 454 private void checkDeletedMatch(Tree tree, 455 IN target, 456 IN parent, 457 int index, 458 boolean requireExactMatch) 459 throws DatabaseException { 460 461 target.latch(); 462 SearchResult result = tree.getParentINForChildIN 463 (target, requireExactMatch, true); 464 assertFalse(result.exactParentFound); 465 assertEquals("Target=" + target + " parent=" + parent, 466 index, result.index); 467 if (requireExactMatch) { 468 assertEquals(null, result.parent); 469 } else { 470 assertEquals(parent, result.parent); 471 parent.releaseLatch(); 472 } 473 } 474 } 475 | Popular Tags |