/** * Converts the given DIN and its descendants. * * <p>Enter/leave with bin field latched, although bin field will change to last inserted slot. */ private void convertDin(final DIN din, final byte[] binKey) { din.latch(); try { for (int i = 0; i < din.getNEntries(); i += 1) { final IN child = din.fetchIN(i, CacheMode.DEFAULT); assert (!child.isBINDelta(false)); if (child instanceof DBIN) { final DBIN dbin = (DBIN) child; dbin.latch(); try { for (int j = 0; j < dbin.getNEntries(); j += 1) { if (!isLNDeleted(dbin, j)) { convertDbinSlot(dbin, j, binKey); } } assert dbin.verifyMemorySize(); /* Count DBIN obsolete. */ if (dbin.getLastLoggedLsn() != DbLsn.NULL_LSN) { localTracker.countObsoleteNodeInexact( dbin.getLastLoggedLsn(), dbin.getLogType(), 0, dbin.getDatabase()); } } finally { dbin.releaseLatch(); } } else { convertDin((DIN) child, binKey); } /* Evict DIN child. */ din.detachNode(i, false /*updateLsn*/, -1 /*lsn*/); } assert din.verifyMemorySize(); /* Count DIN and DupCountLN obsolete. */ if (din.getLastLoggedLsn() != DbLsn.NULL_LSN) { localTracker.countObsoleteNodeInexact( din.getLastLoggedLsn(), din.getLogType(), 0, din.getDatabase()); } final ChildReference dupCountRef = din.getDupCountLNRef(); if (dupCountRef != null && dupCountRef.getLsn() != DbLsn.NULL_LSN) { localTracker.countObsoleteNodeInexact( dupCountRef.getLsn(), LogEntryType.LOG_DUPCOUNTLN, 0, din.getDatabase()); } } finally { din.releaseLatch(); } }
/** * Converts the given DIN and its descendants. * * <p>Enter/leave with bin field latched, although bin field will change to last inserted slot. */ private void convertDin(final DIN din, final byte[] binKey) { din.latch(); try { for (int i = 0; i < din.getNEntries(); i += 1) { final IN child = (IN) din.fetchTargetWithExclusiveLatch(i); if (child instanceof DBIN) { final DBIN dbin = (DBIN) child; dbin.latch(); try { for (int j = 0; j < dbin.getNEntries(); j += 1) { if (!isLNDeleted(dbin, j)) { convertDbinSlot(dbin, j, binKey); } } assert dbin.verifyMemorySize(); /* Count DBIN obsolete. */ if (dbin.getLastLoggedVersion() != DbLsn.NULL_LSN) { localTracker.countObsoleteNodeInexact( dbin.getLastLoggedVersion(), dbin.getLogType(), 0, dbin.getDatabase()); } } finally { dbin.releaseLatch(); } } else { convertDin((DIN) child, binKey); } /* Evict DIN child. */ din.updateNode(i, null, null); envImpl.getInMemoryINs().remove(child); } assert din.verifyMemorySize(); /* Count DIN and DupCountLN obsolete. */ if (din.getLastLoggedVersion() != DbLsn.NULL_LSN) { localTracker.countObsoleteNodeInexact( din.getLastLoggedVersion(), din.getLogType(), 0, din.getDatabase()); } final ChildReference dupCountRef = din.getDupCountLNRef(); if (dupCountRef != null && dupCountRef.getLsn() != DbLsn.NULL_LSN) { localTracker.countObsoleteNodeInexact( dupCountRef.getLsn(), LogEntryType.LOG_DUPCOUNTLN, 0, din.getDatabase()); } } finally { din.releaseLatch(); } }
/** * Converts the given DBIN slot, leaving bin/index set to the inserted BIN slot. * * <p>Enter/leave with bin field latched, although bin field may change. * * <p>If slot is inserted into current bin, leave bin field unchanged and set index field to * inserted slot. * * <p>If slot is inserted into a different bin, set bin/index fields to inserted slot. */ private void convertDbinSlot(final DBIN dbin, final int dbinIndex, final byte[] binKey) { final byte[] newKey = DupKeyData.replaceData(binKey, dbin.getKey(dbinIndex)); if (DEBUG) { System.out.println("DupConvert DBIN LN " + Key.dumpString(newKey, 0)); } /* * If the current BIN can hold the new slot, don't bother to do a * search to find it. */ if (bin.needsSplitting() || !bin.isKeyInBounds(newKey)) { /* Compact keys after finishing with a BIN. */ bin.compactMemory(); /* Evict without latches, before moving to a new BIN. */ bin.releaseLatch(); envImpl.daemonEviction(false /*backgroundIO*/); /* Find a BIN for insertion, split if necessary. */ bin = dbin.getDatabase().getTree().searchSplitsAllowed(newKey, CacheMode.UNCHANGED); } final int newIndex = bin.insertEntry1( null /*ln*/, newKey, null /*data*/, dbin.getLsn(dbinIndex), dbin.getState(dbinIndex), false); if ((newIndex & IN.INSERT_SUCCESS) == 0) { throw EnvironmentFailureException.unexpectedState( "Key not inserted: " + Key.dumpString(newKey, 0) + " DB: " + dbin.getDatabase().getId()); } index = newIndex & ~IN.INSERT_SUCCESS; /* * Evict LN from DBIN slot. Although we don't explicitly load DBIN LNs, * it may have been loaded by recovery. */ dbin.detachNode(dbinIndex, false /*updateLsn*/, -1 /*lsn*/); nConverted += 1; }