/**
   * 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;
  }
Example #2
0
  /**
   * For unit test support:
   *
   * @return a string that dumps information about this IN, without
   */
  @Override
  public String dumpString(int nSpaces, boolean dumpTags) {
    StringBuilder sb = new StringBuilder();
    sb.append(TreeUtils.indent(nSpaces));
    sb.append(beginTag());
    sb.append('\n');

    sb.append(TreeUtils.indent(nSpaces + 2));
    sb.append("<dupkey>");
    sb.append(dupKey == null ? "" : Key.dumpString(dupKey, 0));
    sb.append("</dupkey>");
    sb.append('\n');

    sb.append(super.dumpString(nSpaces, false));

    sb.append(TreeUtils.indent(nSpaces));
    sb.append(endTag());
    return sb.toString();
  }
  /**
   * Converts the bin/index slot, whether a singleton LN or a DIN root.
   *
   * <p>Enter/leave with bin field latched, although bin field may change.
   *
   * <p>When a singleton LN is converted, leaves with bin/index fields unchanged.
   *
   * <p>When a dup tree is converted, leaves with bin/index fields set to last inserted slot. This
   * is the slot of the highest key in the dup tree.
   */
  private void convertBinSlot() {
    if (DEBUG) {
      System.out.println(
          "DupConvert BIN LSN "
              + DbLsn.getNoFormatString(bin.getLsn(index))
              + " index "
              + index
              + " nEntries "
              + bin.getNEntries());
    }
    /* Delete slot if LN is deleted. */
    final boolean isDeleted;
    if (isLNDeleted(bin, index)) {
      deleteSlot();
      return;
    }

    final Node node = bin.fetchLNOrDIN(index, CacheMode.DEFAULT);

    if (!node.containsDuplicates()) {
      if (DEBUG) {
        System.out.println("DupConvert BIN LN " + Key.dumpString(bin.getKey(index), 0));
      }
      /* Fetching a non-deleted LN updates the slot key; we're done. */
      assert node instanceof LN;
      nConverted += 1;
      return;
    }

    /*
     * Delete the slot containing the DIN before re-inserting the dup tree,
     * so that the DIN slot key doesn't interfere with insertions.
     *
     * The DIN is evicted and memory usage is decremented. This is not
     * exactly correct because we keep a local reference to the DIN until
     * the dup tree is converted, but we tolerate this temporary
     * inaccuracy.
     */
    final byte[] binKey = bin.getKey(index);
    final DIN din = (DIN) node;
    deleteSlot();
    convertDin(din, binKey);
  }
Example #4
0
 /** DBINS need to dump their dup key */
 @Override
 protected void dumpLogAdditional(StringBuilder sb) {
   super.dumpLogAdditional(sb);
   sb.append(Key.dumpString(dupKey, 0));
 }