Package com.sleepycat.je.tree

Examples of com.sleepycat.je.tree.IN


       * pass the LSN of the current log entry and also the LSN of the IN
       * in question. The only time these differ is when the log entry is
       * a BINDelta -- then the IN's LSN is the last full version LSN,
       * and the log LSN is the current log entry.
             */
            IN in = reader.getIN();
            long inLsn = reader.getLsnOfIN();
            in.postRecoveryInit(db, inLsn);
            in.latch();
            replaceOrInsert(db, in, reader.getLastLsn(), inLsn,
                            requireExactMatch);
        }

        /*
 
View Full Code Here


        boolean inserted = false;
        boolean replaced = false;
        long originalLsn = DbLsn.NULL_LSN;

        byte[] mainTreeKey = inFromLog.getMainTreeKey();
        IN parent = null;
        int index = -1;
        boolean success = false;
        try {

            /*
             * Allow splits since the parent BIN of this DIN may be full.
             * [#13435]
             */
            parent = db.getTree().searchSplitsAllowed
                (mainTreeKey, -1, true /*updateGeneration*/);
            assert parent instanceof BIN;

      ChildReference newRef =
    new ChildReference(inFromLog, mainTreeKey, lsn);
      index = parent.insertEntry1(newRef);
      if ((index >= 0 &&
     (index & IN.EXACT_MATCH) != 0)) {

    index &= ~IN.EXACT_MATCH;

    /*
     * Replace whatever's at this entry, whether it's an LN or an
     * earlier root DIN as long as one of the following is true:
     *
     * - the entry is known deleted
     * - or the LSN is earlier than the one we've just read from
     *     the log.
     */
    if (parent.isEntryKnownDeleted(index)) {
        /* Be sure to clear the known deleted bit. */
        parent.setEntry(index, inFromLog, mainTreeKey,
            lsn, (byte) 0);
        replaced = true;
    } else {
        originalLsn = parent.getLsn(index);
        if (DbLsn.compareTo(originalLsn, lsn) < 0) {
      parent.setEntry(index, inFromLog, mainTreeKey, lsn,
          parent.getState(index));
      replaced = true;
        }
    }
      } else {
    found = false;
      }
      success = true;
        } finally {
            if (parent != null) {
                parent.releaseLatch();
            }
            trace(detailedTraceLevel,
                  db,
                  TRACE_DUP_ROOT_REPLACE, success, inFromLog,
                  lsn, parent, found,
View Full Code Here

  protected Node fetchLSN(long lsn)
      throws DatabaseException {

      INEntry inEntry = (INEntry) lsnINMap.remove(new Long(lsn));
      assert (inEntry != null);
      IN in = inEntry.in;
      in.latch();
      try {
    int index = inEntry.index;
    if (in.isEntryKnownDeleted(index) ||
        in.getLsn(index) != lsn) {
        return null;
    }
    return in.fetchTarget(index);
      } finally {
    in.releaseLatch();
      }
  }
View Full Code Here

             *
             * If no possible parent is found, the compressor may have deleted
             * this item before we got to processing it.
             */
            if (result.parent != null) {
                IN parent = result.parent;
                int parentLevel = parent.getLevel();
                boolean mustLogParent = false;

                /*
                 * If bottomLevelTarget is true, the parent IN contains bottom
                 * level BINs -- either DBINs or BINs depending on whether dups
                 * are configured or not.  If dups are configured we cannot
                 * mask the level, since we do not want to select the parent of
                 * a BIN in the upper part of the tree.  The masking is used to
                 * normalize the level for ordinary non-dup DBs and the mapping
                 * tree DB.
                 */
                boolean bottomLevelTarget = db.getSortedDuplicates() ?
                    (parentLevel == 2) :
                    ((parentLevel & IN.LEVEL_MASK) == 2);

                /*
                 * INs at the max flush level are always non-provisional and
                 * INs at the bottom level (when this is not also the max flush
                 * level) are always provisional.  In between INs are
                 * provisional BEFORE_CKPT_END (see Provisional).
                 *
                 * Note that to determine whether this IN is at the
                 * maxFlushLevel, we check (parentLevel > maxFlushLevel)
                 * instead of (currentLevel >= maxFlushLevel).  This handles
                 * the case where this IN is a DIN root, and the parent is a
                 * BIN that will not be flushed because the maxFlushLevel is
                 * less than IN.MAIN_LEVEL (0x10000).  For example, this IN is
                 * a DIN root at level 2 and the maxFlushLevel is 3.  [#16712]
                 */
                Provisional provisional;
                if (parentLevel > maxFlushLevel) {
                    provisional = Provisional.NO;
                } else if (bottomLevelTarget) {
                    provisional = Provisional.YES;
                } else {
                    provisional = Provisional.BEFORE_CKPT_END;
                }

                /*
                 * Log a sub-tree when the target is at the bottom level and
                 * this is not a recursive call to flushIN during sub-tree
                 * logging.
                 */
                boolean logSubtree = bottomLevelTarget && allowLogSubtree;

                /*
                 * Log sub-tree siblings with the latch held when highPriority
                 * is configured and this is not a DW DB.  For a DW DB, dirty
                 * LNs are logged for each BIN.  If we were to log a DW
                 * sub-tree with the parent latch held, the amount of logging
                 * may cause the latch to be held for too long a period.
                 */
                boolean logSiblingsWithParentLatchHeld =
                    logSubtree &&
                    highPriority &&
                    !db.isDurableDeferredWrite();

                /*
                 * If we log siblings with the parent latch held, we log the
                 * target along with other siblings so we can perform a single
                 * multi-log call for all siblings.
                 */
                boolean logTargetWithOtherSiblings = false;

                /*
                 * Map of node ID to parent index for each sibling to log.  We
                 * must process the siblings in node ID order during multi-log,
                 * so that latching order is deterministic and only in one
                 * direction.
                 */
                SortedMap<Long,Integer> siblingsToLog = null;

                try {
                    if (result.exactParentFound) {

                        /*
                         * If the child has already been evicted, don't
                         * refetch it.
                         */
                        IN renewedTarget = (IN) parent.getTarget(result.index);

                        if (renewedTarget == null) {
                            /* nAlreadyEvictedThisRun++;  -- for future */
                            mustLogParent |= true;
                        } else {
                            if (logSiblingsWithParentLatchHeld) {
                                logTargetWithOtherSiblings = true;
                            } else {
                                mustLogParent |= logSiblings
                                    (envImpl, dirtyMap, parent,
                                     Collections.singleton(result.index),
                                     allowDeltas, checkpointStart,
                                     highPriority, provisional, fstats,
                                     localTracker);
                            }
                        }
                    } else {
                        /* result.exactParentFound was false. */

                        /* Do not flush children of the inexact parent. */
                        logSubtree = false;

                        if (result.childNotResident) {

                            /*
                             * But it was because the child wasn't resident.
                             * To be on the safe side, we'll put the parent
                             * into the dirty set to be logged when that level
                             * is processed.
                             *
                             * Only do this if the parent we found is at a
                             * higher level than the child.  This ensures that
                             * the non-exact search does not find a sibling
                             * rather than a parent. [#11555]
                             */
                            if (parentLevel > currentLevel) {
                                mustLogParent |= true;
                            }
                            /* nAlreadyEvictedThisRun++; -- for future. */
                        }
                    }

                    if (logSubtree) {

                        /*
                         * Create a map of node ID to parent index for each
                         * sibling we intend to log.  Note that the dirty map
                         * does not contain targetRef (the sibling we're
                         * processing) because it was removed before calling
                         * this method, but it is added to the map below.
                         *
                         * A TreeMap (sorted map) is used so that siblings are
                         * latched in node ID order.  A deterministic order is
                         * needed to avoid deadlocks, if siblings are latched
                         * in multiple threads in the future.
                         */
                        siblingsToLog = new TreeMap<Long,Integer>();
                        for (int index = 0;
                             index < parent.getNEntries();
                             index += 1) {
                            Node child = parent.getTarget(index);
                            if (child != null) {
                                Long childId = child.getNodeId();
                                if ((logTargetWithOtherSiblings &&
                                     targetRef.nodeId ==
                                     childId.longValue()) ||
                                    dirtyMap.containsNode
                                        (child.getLevel(), childId)) {
                                    siblingsToLog.put(childId, index);
                                }
                            }
                        }

                        if (logSiblingsWithParentLatchHeld) {
                            if (MULTI_LOG) {
                                mustLogParent |= logSiblings
                                    (envImpl, dirtyMap, parent,
                                     siblingsToLog.values(), allowDeltas,
                                     checkpointStart, highPriority,
                                     provisional, fstats, localTracker);
                            } else {
                                for (int index : siblingsToLog.values()) {
                                    IN child = (IN) parent.getTarget(index);
                                    CheckpointReference childRef =
                                        (targetRef.nodeId ==
                                         child.getNodeId()) ? targetRef :
                                        dirtyMap.removeNode(child.getLevel(),
                                                            child.getNodeId());
                                    assert childRef != null;
                                    mustLogParent |= logSiblings
                                        (envImpl, dirtyMap, parent,
                                         Collections.singleton(index),
                                         allowDeltas, checkpointStart,
View Full Code Here

        boolean mustLogParent = false;
        List<INLogItem> itemList = new ArrayList<INLogItem>();

        try {
            for (int index : indicesToLog) {
                IN child = (IN) parent.getTarget(index);

                /* Remove it from dirty map if it is present. */
                dirtyMap.removeNode(child.getLevel(), child.getNodeId());

                /*
                 * Latch and add item with valid parentIndex, so we will
                 * release the latch in the finally statement.
                 */
                child.latch(CacheMode.UNCHANGED);
                INLogItem item = new INLogItem();
                item.parentIndex = index;
                itemList.add(item);

                /*
                 * Compress this node if necessary. Note that this may dirty
                 * the node.
                 */
                envImpl.lazyCompress(child, localTracker);

                if (child.getDirty()) {

                    if (child.getDatabase().isDurableDeferredWrite()) {

                        /*
                         * Find dirty descendants to avoid logging nodes with
                         * never-logged children. See [#13936] and
                         * IN.logDirtyChildren for description of the case.
                         *
                         * Note that we must log both dirty and never-logged
                         * descendants to be sure to have a consistent view of
                         * the split. If we didn't, we could end up with the
                         * post-split version of a new sibling and the
                         * pre-split version of an split sibling in the log,
                         * which could result in a recovery where descendants
                         * are incorrectly duplicated, because they are in both
                         * the pre-split split sibling, and the post-split
                         * version of the new sibling.
                         */
                        child.logDirtyChildren();
                    }

                    /* Set default params. */
                    item.provisional = provisional;
                    item.repContext = ReplicationContext.NO_REPLICATE;
                    item.parent = parent;

                    /*
                     * Allow child to perform "before log" processing.  Note
                     * that child decides whether to log a delta. Only BINs
                     * that fall into the required percentages and have not
                     * been cleaned will be logged with a delta.
                     */
                    child.beforeLog(logManager, item, context);
                } else {
                    /* Do not process if not dirty.  Unlatch now. */
                    itemList.remove(itemList.size() - 1);
                    child.releaseLatch();

                    /* Log parent if child has already been flushed. */
                    mustLogParent = true;
                }
            }

            /*
             * Log all siblings at once.  Limitations of Java generics prevent
             * conversion from List<INLogItem> to List<LogItem> even by
             * casting, so we convert to an array instead.
             */
            LogItem[] itemArray = new LogItem[itemList.size()];
            logManager.multiLog(itemList.toArray(itemArray), context);

            for (INLogItem item : itemList) {
                IN child = (IN) parent.getTarget(item.parentIndex);

                /* Allow child to perform "after log" processing. */
                child.afterLog(logManager, item, context);

                /*
                 * When logging a delta, if the BIN was already logged after
                 * checkpoint start and before this point (i.e. by an
                 * eviction), we must make sure that the last full version is
                 * accessible from ancestors. We can skip logging parents only
                 * if the last full version was not logged in this checkpoint
                 * interval.
                 */
                boolean logThisParent = true;
                if (allowDeltas && (item.newLsn == DbLsn.NULL_LSN)) {
                    fstats.nDeltaINFlushThisRun++;
                    fstats.nDeltaINFlush++;
                    if (DbLsn.compareTo(child.getLastFullVersion(),
                                        checkpointStart) < 0) {
                        logThisParent = false;
                    }
                }
                if (logThisParent) {
                    mustLogParent = true;
                }

                /* Update the parent if a full version was logged. */
                if (item.newLsn != DbLsn.NULL_LSN) {
                    fstats.nFullINFlushThisRun++;
                    fstats.nFullINFlush++;
                    if (child instanceof BIN) {
                        fstats.nFullBINFlush++;
                        fstats.nFullBINFlushThisRun++;
                    }
                    parent.updateEntry(item.parentIndex, item.newLsn);
                }
            }
            return mustLogParent;
        } finally {
            for (INLogItem item : itemList) {
                IN child = (IN) parent.getTarget(item.parentIndex);
                child.releaseLatch();
            }
        }
    }
View Full Code Here

            throws DatabaseException {

            if (root == null) {
                return null;
            }
            IN rootIN = (IN) root.fetchTarget(db, null);
            rootIN.latch(CacheMode.UNCHANGED);
            try {
                if (rootIN.getNodeId() == targetNodeId) {

                    /*
                     * Find dirty descendants to avoid logging nodes with
                     * never-logged children. See [#13936]
                     */
                    if (rootIN.getDatabase().isDurableDeferredWrite()) {
                        rootIN.logDirtyChildren();
                    }

                    /*
                     * stillRoot handles the situation where the root was split
                     * after it was placed in the checkpointer's dirty set.
                     */
                    stillRoot = true;
                    if (rootIN.getDirty()) {
                        long newLsn = rootIN.log(logManager);
                        root.setLsn(newLsn);
                        flushed = true;
                    }
                }
            } finally {
                rootIN.releaseLatch();
            }
            return null;
        }
View Full Code Here

             * over the IN list(s).
             */
            while ((evictBytes < reqEvictBytes) &&
                   (nNodesScannedThisRun <= maxINsPerBatch)) {

                IN target = selectIN(maxINsPerBatch);

                if (target == null) {
                    break;
                } else {
                    assert evictProfile.count(target);//intentional side effect

                    /*
                     * Check to make sure the DB was not deleted after
                     * selecting it, and prevent the DB from being deleted
                     * while we're working with it.
                     */
                    DatabaseImpl targetDb = target.getDatabase();
                    DbTree dbTree = targetDb.getDbEnvironment().getDbTree();
                    DatabaseImpl refreshedDb = null;
                    try {
                        refreshedDb = dbTree.getDb(targetDb.getId());
                        if (refreshedDb != null && !refreshedDb.isDeleted()) {
                            if (target.isDbRoot()) {
                                evictBytes += evictRoot(target, backgroundIO);
                            } else {
                                evictBytes += evictIN(target, backgroundIO,
                                                      source);
                            }
                        } else {

                            /*
                             * We don't expect to see an IN that is resident on
                             * the INList with a database that has finished
                             * delete processing, because it should have been
                             * removed from the INList during post-delete
                             * cleanup.  It may have been returned by the
                             * INList iterator after being removed from the
                             * INList (because we're using ConcurrentHashMap),
                             * but then IN.getInListResident should return
                             * false.
                             */
                            if (targetDb.isDeleteFinished() &&
                                target.getInListResident()) {
                                String inInfo =
                                    " IN type=" + target.getLogType() +
                                    " id=" + target.getNodeId() +
                                    " not expected on INList";
                                String errMsg = (refreshedDb == null) ?
                                    inInfo :
                                    ("Database " + refreshedDb.getDebugName() +
                                     " id=" + refreshedDb.getId() +
View Full Code Here

    /**
     * Select a single node to evict.
     */
    private IN selectIN(int maxNodesToIterate) {
        /* Find the best target in the next <nodesPerScan> nodes. */
        IN target = null;
        long targetGeneration = Long.MAX_VALUE;
        int targetLevel = Integer.MAX_VALUE;
        boolean targetDirty = true;

        /* The nodesPerScan limit is on nodes that qualify for eviction. */
        int nCandidates = 0;

        /* The limit on iterated nodes is to prevent an infinite loop. */
        int nIterated = 0;

        while (nIterated <  maxNodesToIterate && nCandidates < nodesPerScan) {
            IN in = getNextIN();
            if (in == null) {
                break; // INList is empty
            }
            nIterated++;
            nNodesScannedThisRun++;

            DatabaseImpl db = in.getDatabase();

            /*
             * Ignore the IN if its database is deleted.  We have not called
             * getDb, so we can't guarantee that the DB is valid; get Db is
             * called and this is checked again after an IN is selected for
             * eviction.
             */
            if (db == null || db.isDeleted()) {
                continue;
            }

            /*
             * If this is a read-only environment, skip any dirty INs (recovery
             * dirties INs even in a read-only environment).
             */
            if (db.getDbEnvironment().isReadOnly() &&
                in.getDirty()) {
                continue;
            }

            /*
             * Only scan evictable or strippable INs.  This prevents higher
             * level INs from being selected for eviction, unless they are
             * part of an unused tree.
             */
            int evictType = in.getEvictionType();
            if (evictType == IN.MAY_NOT_EVICT) {
                continue;
            }

            /*
             * This node is in the scanned node set.  Select according to
             * the configured eviction policy.
             */
            if (evictByLruOnly) {

                /*
                 * Select the node with the lowest generation number,
                 * irrespective of tree level or dirtyness.
                 */
                if (targetGeneration > in.getGeneration()) {
                    targetGeneration = in.getGeneration();
                    target = in;
                }
            } else {

                /*
                 * Select first by tree level, then by dirtyness, then by
                 * generation/LRU.
                 */
                int level = normalizeLevel(in, evictType);
                if (targetLevel != level) {
                    if (targetLevel > level) {
                        targetLevel = level;
                        targetDirty = in.getDirty();
                        targetGeneration = in.getGeneration();
                        target = in;
                    }
                } else if (targetDirty != in.getDirty()) {
                    if (targetDirty) {
                        targetDirty = false;
                        targetGeneration = in.getGeneration();
                        target = in;
                    }
                } else {
                    if (targetGeneration > in.getGeneration()) {
                        targetGeneration = in.getGeneration();
                        target = in;
                    }
                }
            }
            nCandidates++;
View Full Code Here

            long evictBytes = 0;

            public IN doWork(ChildReference root)
                throws DatabaseException {

                IN rootIN = (IN) root.fetchTarget(db, null);
                rootIN.latch(CacheMode.UNCHANGED);
                try {
                    /* Re-check that all conditions still hold. */
                    boolean isDirty = rootIN.getDirty();
                    if (rootIN == target &&
                        rootIN.isDbRoot() &&
                        rootIN.isEvictable() &&
                        !(envImpl.isReadOnly() && isDirty)) {

                        /* Flush if dirty. */
                        if (isDirty) {
                            long newLsn = rootIN.log
                                (envImpl.getLogManager(),
                                 false, // allowDeltas
                                 isProvisionalRequired(rootIN),
                                 backgroundIO,
                                 null); // parent
                            root.setLsn(newLsn);
                            flushed = true;
                        }

                        /* Take off the INList and adjust memory budget. */
                        inList.remove(rootIN);
                        evictBytes = rootIN.getBudgetedMemorySize();

                        /* Evict IN. */
                        root.clearTarget();

                        /* Stats */
                        nRootNodesEvicted.increment();
                    }
                } finally {
                    rootIN.releaseLatch();
                }
                return null;
            }
        }

View Full Code Here

            /*
             * Get a new reference to the child, in case the reference
             * saved in the selection list became out of date because of
             * changes to that parent.
             */
            IN renewedChild = (IN) parent.getTarget(index);

            if (renewedChild == null) {
                return evictBytes;
            }
           
            boolean inline = (source == EvictionSource.CACHEMODE);
            if (!inline && renewedChild.getGeneration() > oldGenerationCount) {
                return evictBytes;
            }

            /*
             * See the evictIN() method in this class for an explanation for
             * calling latchNoWait().
             */
            if (inline) {
                renewedChild.latch(CacheMode.UNCHANGED);
            } else {
                if (!renewedChild.latchNoWait(CacheMode.UNCHANGED)) {
                    return evictBytes;
                }
            }
            try {
                if (!renewedChild.isEvictable()) {
                    return evictBytes;
                }

                DatabaseImpl db = renewedChild.getDatabase();
                /* Do not use superclass envImpl. */
                EnvironmentImpl envImpl = db.getDbEnvironment();

                /*
                 * Log the child if dirty and env is not r/o. Remove
                 * from IN list.
                 */
                long renewedChildLsn = DbLsn.NULL_LSN;
                boolean newChildLsn = false;
                if (renewedChild.getDirty()) {
                    if (!envImpl.isReadOnly()) {
                        boolean logProvisional =
                            isProvisionalRequired(renewedChild);

                        /*
                         * Log a full version (no deltas) and with
                         * cleaner migration allowed.
                         */
                        renewedChildLsn = renewedChild.log
                            (envImpl.getLogManager(),
                             false, // allowDeltas
                             logProvisional,
                             backgroundIO,
                             parent);
                        newChildLsn = true;
                    }
                } else {
                    renewedChildLsn = parent.getLsn(index);
                }

                if (renewedChildLsn != DbLsn.NULL_LSN) {
                    /* Take this off the inlist. */
                    envImpl.getInMemoryINs().remove(renewedChild);

                    evictBytes = renewedChild.getBudgetedMemorySize();
                    if (newChildLsn) {

                        /*
                         * Update the parent so its reference is
                         * null and it has the proper LSN.
                         */
                        parent.updateNode
                            (index, null /*node*/, renewedChildLsn,
                             null /*lnSlotKey*/);
                    } else {

                        /*
                         * Null out the reference, but don't dirty
                         * the node since only the reference
                         * changed.
                         */
                        parent.updateNode
                            (index, (Node) null /*node*/,
                             null /*lnSlotKey*/);
                    }

                    /* Stats */
                    nNodesEvicted.increment();
                    renewedChild.incEvictStats(source);
                }
            } finally {
                renewedChild.releaseLatch();
            }
        } finally {
            parent.releaseLatch();
        }

View Full Code Here

TOP

Related Classes of com.sleepycat.je.tree.IN

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.