KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > incomp > INCompressor


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: INCompressor.java,v 1.125 2006/10/30 21:14:17 bostic Exp $
7  */

8
9 package com.sleepycat.je.incomp;
10
11 import java.util.ArrayList JavaDoc;
12 import java.util.Collection JavaDoc;
13 import java.util.HashMap JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.logging.Level JavaDoc;
18
19 import com.sleepycat.je.DatabaseException;
20 import com.sleepycat.je.EnvironmentStats;
21 import com.sleepycat.je.StatsConfig;
22 import com.sleepycat.je.cleaner.TrackedFileSummary;
23 import com.sleepycat.je.cleaner.UtilizationTracker;
24 import com.sleepycat.je.config.EnvironmentParams;
25 import com.sleepycat.je.dbi.DatabaseImpl;
26 import com.sleepycat.je.dbi.DbTree;
27 import com.sleepycat.je.dbi.EnvironmentImpl;
28 import com.sleepycat.je.latch.LatchSupport;
29 import com.sleepycat.je.tree.BIN;
30 import com.sleepycat.je.tree.BINReference;
31 import com.sleepycat.je.tree.CursorsExistException;
32 import com.sleepycat.je.tree.DBIN;
33 import com.sleepycat.je.tree.DIN;
34 import com.sleepycat.je.tree.IN;
35 import com.sleepycat.je.tree.Key;
36 import com.sleepycat.je.tree.Node;
37 import com.sleepycat.je.tree.NodeNotEmptyException;
38 import com.sleepycat.je.tree.Tree;
39 import com.sleepycat.je.tree.Tree.SearchType;
40 import com.sleepycat.je.utilint.DaemonThread;
41 import com.sleepycat.je.utilint.PropUtil;
42 import com.sleepycat.je.utilint.Tracer;
43
44 /**
45  * The IN Compressor. JE compression consist of removing delete entries from
46  * BINs, and pruning empty IN/BINs from the tree. Compression is carried out by
47  * either a daemon thread or lazily by operations (namely checkpointing and
48  * eviction) that are writing INS.
49  */

50 public class INCompressor extends DaemonThread {
51     private static final String JavaDoc TRACE_COMPRESS = "INCompress:";
52     private static final boolean DEBUG = false;
53
54     private EnvironmentImpl env;
55     private long lockTimeout;
56
57     /* stats */
58     private int splitBins = 0;
59     private int dbClosedBins = 0;
60     private int cursorsBins = 0;
61     private int nonEmptyBins = 0;
62     private int processedBins = 0;
63     
64     /* per-run stats */
65     private int splitBinsThisRun = 0;
66     private int dbClosedBinsThisRun = 0;
67     private int cursorsBinsThisRun = 0;
68     private int nonEmptyBinsThisRun = 0;
69     private int processedBinsThisRun = 0;
70
71     /*
72      * The following stats are not kept per run, because they're set by
73      * multiple threads doing lazy compression. They are debugging aids; it
74      * didn't seem like a good idea to add synchronization to the general path.
75      */

76     private int lazyProcessed = 0;
77     private int lazyEmpty = 0;
78     private int lazySplit = 0;
79     private int wokenUp = 0;
80
81     /*
82      * Store logical references to BINs that have deleted entries and are
83      * candidates for compaction.
84      */

85     private Map JavaDoc binRefQueue;
86     private Object JavaDoc binRefQueueSync;
87
88     public INCompressor(EnvironmentImpl env, long waitTime, String JavaDoc name)
89     throws DatabaseException {
90
91     super(waitTime, name, env);
92         this.env = env;
93     lockTimeout = PropUtil.microsToMillis(
94             env.getConfigManager().getLong
95                 (EnvironmentParams.COMPRESSOR_LOCK_TIMEOUT));
96         binRefQueue = new HashMap JavaDoc();
97         binRefQueueSync = new Object JavaDoc();
98     }
99
100     public String JavaDoc toString() {
101     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
102     sb.append("<INCompressor name=\"").append(name).append("\"/>");
103     return sb.toString();
104     }
105
106     synchronized public void clearEnv() {
107     env = null;
108     }
109
110     public synchronized void verifyCursors()
111     throws DatabaseException {
112
113     /*
114      * Environment may have been closed. If so, then our job here is done.
115      */

116     if (env.isClosed()) {
117         return;
118     }
119
120     /*
121      * Use a snapshot to verify the cursors. This way we don't have to
122      * hold a latch while verify takes locks.
123      */

124     List JavaDoc queueSnapshot = null;
125     synchronized (binRefQueueSync) {
126         queueSnapshot = new ArrayList JavaDoc(binRefQueue.values());
127         }
128
129         /* Use local caching to reduce DbTree.getDb overhead. */
130         Map JavaDoc dbCache = new HashMap JavaDoc();
131
132     Iterator JavaDoc it = queueSnapshot.iterator();
133     while (it.hasNext()) {
134         BINReference binRef = (BINReference) it.next();
135             DatabaseImpl db = env.getDbMapTree().getDb
136                 (binRef.getDatabaseId(), lockTimeout, dbCache);
137         BIN bin = searchForBIN(db, binRef);
138         if (bin != null) {
139         bin.verifyCursors();
140         bin.releaseLatch();
141         }
142     }
143     }
144
145     /**
146      * The default daemon work queue is not used because we need a map, not a
147      * set.
148      */

149     public void addToQueue(Object JavaDoc o)
150     throws DatabaseException {
151
152         throw new DatabaseException
153             ("INCompressor.addToQueue should never be called.");
154     }
155
156     public int getBinRefQueueSize()
157         throws DatabaseException {
158
159         int size = 0;
160         synchronized (binRefQueueSync) {
161             size = binRefQueue.size();
162         }
163
164         return size;
165     }
166
167     /*
168      * There are multiple flavors of the addBin*ToQueue methods. All allow
169      * the caller to specify whether the daemon should be notified. Currently
170      * no callers proactively notify, and we rely on lazy compression and
171      * the daemon timebased wakeup to process the queue.
172      */

173
174     /**
175      * Adds the BIN and deleted Key to the queue if the BIN is not already in
176      * the queue, or adds the deleted key to an existing entry if one exists.
177      */

178     public void addBinKeyToQueue(BIN bin, Key deletedKey, boolean doWakeup)
179     throws DatabaseException {
180
181         synchronized (binRefQueueSync) {
182             addBinKeyToQueueAlreadyLatched(bin, deletedKey);
183         }
184         if (doWakeup) {
185             wakeup();
186         }
187     }
188
189     /**
190      * Adds the BINReference to the queue if the BIN is not already in the
191      * queue, or adds the deleted keys to an existing entry if one exists.
192      */

193     public void addBinRefToQueue(BINReference binRef, boolean doWakeup)
194     throws DatabaseException {
195
196         synchronized (binRefQueueSync) {
197             addBinRefToQueueAlreadyLatched(binRef);
198         }
199
200         if (doWakeup) {
201             wakeup();
202         }
203     }
204
205     /**
206      * Adds an entire collection of BINReferences to the queue at once. Use
207      * this to avoid latching for each add.
208      */

209     public void addMultipleBinRefsToQueue(Collection JavaDoc binRefs,
210                                           boolean doWakeup)
211     throws DatabaseException {
212
213     synchronized (binRefQueueSync) {
214             Iterator JavaDoc it = binRefs.iterator();
215             while (it.hasNext()) {
216                 BINReference binRef = (BINReference) it.next();
217                 addBinRefToQueueAlreadyLatched(binRef);
218             }
219         }
220         
221         if (doWakeup) {
222             wakeup();
223         }
224     }
225
226     /**
227      * Adds the BINReference with the latch held.
228      */

229     private void addBinRefToQueueAlreadyLatched(BINReference binRef) {
230
231         Long JavaDoc node = new Long JavaDoc(binRef.getNodeId());
232         BINReference existingRef = (BINReference) binRefQueue.get(node);
233         if (existingRef != null) {
234             existingRef.addDeletedKeys(binRef);
235         } else {
236             binRefQueue.put(node, binRef);
237         }
238     }
239
240     /**
241      * Adds the BIN and deleted Key with the latch held.
242      */

243     private void addBinKeyToQueueAlreadyLatched(BIN bin, Key deletedKey) {
244
245         Long JavaDoc node = new Long JavaDoc(bin.getNodeId());
246         BINReference existingRef = (BINReference) binRefQueue.get(node);
247         if (existingRef != null) {
248             if (deletedKey != null) {
249                 existingRef.addDeletedKey(deletedKey);
250             }
251         } else {
252             BINReference binRef = bin.createReference();
253             if (deletedKey != null) {
254                 binRef.addDeletedKey(deletedKey);
255             }
256             binRefQueue.put(node, binRef);
257         }
258     }
259
260     public boolean exists(long nodeId) {
261         Long JavaDoc node = new Long JavaDoc(nodeId);
262         synchronized (binRefQueueSync) {
263             return (binRefQueue.get(node) != null);
264     }
265     }
266
267     /*
268      * Return a bin reference for this node if it exists and has a set of
269      * deletable keys.
270      */

271     private BINReference removeCompressibleBinReference(long nodeId) {
272         Long JavaDoc node = new Long JavaDoc(nodeId);
273         BINReference foundRef = null;
274         synchronized (binRefQueueSync) {
275             BINReference target = (BINReference) binRefQueue.remove(node);
276             if (target != null) {
277                 if (target.deletedKeysExist()) {
278                     foundRef = target;
279                 } else {
280
281                     /*
282                      * This is an entry that needs to be pruned. Put it back
283                      * to be dealt with by the daemon.
284                      */

285                     binRefQueue.put(node, target);
286                 }
287             }
288         }
289         return foundRef;
290     }
291
292     /**
293      * Return stats
294      */

295     public void loadStats(StatsConfig config, EnvironmentStats stat)
296         throws DatabaseException {
297
298         stat.setSplitBins(splitBins);
299         stat.setDbClosedBins(dbClosedBins);
300         stat.setCursorsBins(cursorsBins);
301         stat.setNonEmptyBins(nonEmptyBins);
302         stat.setProcessedBins(processedBins);
303         stat.setInCompQueueSize(getBinRefQueueSize());
304
305         if (DEBUG) {
306             System.out.println("lazyProcessed = " + lazyProcessed);
307             System.out.println("lazyEmpty = " + lazyEmpty);
308             System.out.println("lazySplit = " + lazySplit);
309             System.out.println("wokenUp=" + wokenUp);
310         }
311
312         if (config.getClear()) {
313             splitBins = 0;
314             dbClosedBins = 0;
315             cursorsBins = 0;
316             nonEmptyBins = 0;
317             processedBins = 0;
318             lazyProcessed = 0;
319             lazyEmpty = 0;
320             lazySplit = 0;
321             wokenUp = 0;
322         }
323     }
324
325     /**
326      * Return the number of retries when a deadlock exception occurs.
327      */

328     protected int nDeadlockRetries()
329         throws DatabaseException {
330
331         return env.getConfigManager().getInt
332             (EnvironmentParams.COMPRESSOR_RETRY);
333     }
334
335     public synchronized void onWakeup()
336     throws DatabaseException {
337
338         if (env.isClosed()) {
339             return;
340         }
341         wokenUp++;
342         doCompress();
343     }
344
345     /**
346      * The real work to doing a compress. This may be called by the compressor
347      * thread or programatically.
348      */

349     public synchronized void doCompress()
350         throws DatabaseException {
351
352     if (!isRunnable()) {
353         return;
354     }
355
356     /*
357          * Make a snapshot of the current work queue so the compressor thread
358          * can safely iterate over the queue. Note that this impacts lazy
359          * compression, because it lazy compressors will not see BINReferences
360          * that have been moved to the snapshot.
361          */

362         Map JavaDoc queueSnapshot = null;
363         int binQueueSize = 0;
364         synchronized (binRefQueueSync) {
365             binQueueSize = binRefQueue.size();
366             if (binQueueSize > 0) {
367                 queueSnapshot = binRefQueue;
368                 binRefQueue = new HashMap JavaDoc();
369             }
370         }
371
372         /* There is work to be done. */
373         if (binQueueSize > 0) {
374             resetPerRunCounters();
375             Tracer.trace(Level.FINE, env,
376                          "InCompress.doCompress called, queue size: " +
377                          binQueueSize);
378             assert LatchSupport.countLatchesHeld() == 0;
379             
380             /*
381              * Compressed entries must be counted as obsoleted. A separate
382              * tracker is used to accumulate tracked obsolete info so it can be
383              * added in a single call under the log write latch. We log the
384              * info for deleted subtrees immediately because we don't process
385              * deleted IN entries during recovery; this reduces the chance of
386              * lost info.
387              */

388             UtilizationTracker tracker = new UtilizationTracker(env);
389
390             /* Use local caching to reduce DbTree.getDb overhead. */
391             Map JavaDoc dbCache = new HashMap JavaDoc();
392
393             DbTree dbTree = env.getDbMapTree();
394             BINSearch binSearch = new BINSearch();
395             try {
396                 Iterator JavaDoc it = queueSnapshot.values().iterator();
397                 while (it.hasNext()) {
398                     if (env.isClosed()) {
399                         return;
400                     }
401
402                     BINReference binRef = (BINReference) it.next();
403                     if (!findDBAndBIN(binSearch, binRef, dbTree, dbCache)) {
404
405                         /*
406                          * Either the db is closed, or the BIN doesn't
407                          * exist. Don't process this BINReference.
408                          */

409                         continue;
410                     }
411                     
412                     if (binRef.deletedKeysExist()) {
413                         /* Compress deleted slots. */
414                         boolean requeued = compressBin
415                             (binSearch.db, binSearch.bin, binRef, tracker);
416
417                         if (!requeued) {
418
419                             /*
420                              * This BINReference was fully processed, but there
421                  * may still be deleted slots. If there are still
422                  * deleted keys in the binref, they were relocated
423                  * by a split.
424                              */

425                             checkForRelocatedSlots
426                                 (binSearch.db, binRef, tracker);
427                         }
428                     } else {
429
430                         /*
431                          * An empty BINReference on the queue was put there by
432                          * a lazy compressor to indicate that we should try to
433                          * prune an empty BIN.
434                          */

435                         BIN foundBin = binSearch.bin;
436
437                         byte[] idKey = foundBin.getIdentifierKey();
438                         boolean isDBIN = foundBin.containsDuplicates();
439                         byte[] dupKey = null;
440                         if (isDBIN) {
441                             dupKey = ((DBIN) foundBin).getDupKey();
442                         }
443
444                         /*
445                          * Release the bin latch taken by the initial
446                          * search. Pruning starts from the top of the tree
447                          * and requires that no latches are held.
448                          */

449                         foundBin.releaseLatch();
450                         
451                         pruneBIN(binSearch.db, binRef, idKey, isDBIN,
452                                  dupKey, tracker);
453                     }
454                 }
455
456                 /*
457                  * Count obsolete nodes and write out modified file summaries
458                  * for recovery. All latches must have been released.
459                  */

460                 TrackedFileSummary[] summaries = tracker.getTrackedFiles();
461                 if (summaries.length > 0) {
462                     env.getUtilizationProfile().countAndLogSummaries
463                         (summaries);
464                 }
465                 
466             } finally {
467                 assert LatchSupport.countLatchesHeld() == 0;
468                 accumulatePerRunCounters();
469             }
470         }
471     }
472
473     /**
474      * Compresses a single BIN and then deletes the BIN if it is empty.
475      * @param bin is latched when this method is called, and unlatched when it
476      * returns.
477      * @return true if the BINReference was requeued by this method.
478      */

479     private boolean compressBin(DatabaseImpl db,
480                                 BIN bin,
481                                 BINReference binRef,
482                                 UtilizationTracker tracker)
483         throws DatabaseException {
484
485         /* Safe to get identifier keys; bin is latched. */
486         boolean empty = false;
487         boolean requeued = false;
488         byte[] idKey = bin.getIdentifierKey();
489         byte[] dupKey = null;
490         boolean isDBIN = bin.containsDuplicates();
491             
492         try {
493             int nCursors = bin.nCursors();
494             if (nCursors > 0) {
495
496                 /*
497                  * There are cursors pointing to the BIN, so try again later.
498                  */

499                 addBinRefToQueue(binRef, false);
500                 requeued = true;
501                 cursorsBinsThisRun++;
502             } else {
503                 requeued = bin.compress(binRef, true /* canFetch */);
504                 if (!requeued) {
505
506                     /*
507                      * Only check for emptiness if this BINRef is in play and
508                      * not on the queue.
509                      */

510                     empty = (bin.getNEntries() == 0);
511
512                     if (empty) {
513
514                         /*
515                          * While we have the BIN latched, prepare a dup key if
516                          * needed for navigating the tree while pruning.
517                          */

518                         if (isDBIN) {
519                             dupKey = ((DBIN) bin).getDupKey();
520                         }
521                     }
522                 }
523             }
524         } finally {
525             bin.releaseLatch();
526         }
527
528         /* Prune if the bin is empty and there has been no requeuing. */
529         if (empty) {
530             requeued = pruneBIN(db, binRef, idKey, isDBIN, dupKey, tracker);
531         }
532
533         return requeued;
534     }
535
536     /**
537      * If the target BIN is empty, attempt to remove the empty branch of the
538      * tree.
539      * @return true if the pruning was unable to proceed and the BINReference
540      * was requeued.
541      */

542     private boolean pruneBIN(DatabaseImpl dbImpl,
543                              BINReference binRef,
544                              byte[] idKey,
545                              boolean containsDups,
546                              byte[] dupKey,
547                              UtilizationTracker tracker)
548         throws DatabaseException {
549
550         boolean requeued = false;
551         try {
552             Tree tree = dbImpl.getTree();
553             
554             if (containsDups) {
555                 tree.deleteDup(idKey, dupKey, tracker);
556             } else {
557                 tree.delete(idKey, tracker);
558             }
559             processedBinsThisRun++;
560         } catch (NodeNotEmptyException NNEE) {
561
562             /*
563              * Something was added to the node since the point when the
564              * deletion occurred; we can't prune, and we can throw away this
565              * BINReference.
566              */

567              nonEmptyBinsThisRun++;
568         } catch (CursorsExistException e) {
569
570             /*
571              * If there are cursors in the way of the delete, retry later.
572              * For example, When we delete a BIN or DBIN, we're guaranteed that
573              * there are no cursors at that node. (otherwise, we wouldn't be
574              * able to remove all the entries. However, there's the possibility
575              * that the BIN that is the parent of the duplicate tree has
576              * resident cursors, and in that case, we would not be able to
577              * remove the whole duplicate tree and DIN root. In that case, we'd
578              * requeue.
579              */

580             addBinRefToQueue(binRef, false);
581             cursorsBinsThisRun++;
582             requeued = true;
583         }
584         return requeued;
585     }
586     
587     /*
588      * When we do not requeue the BINRef but there are deleted keys remaining,
589      * those keys were not found in the BIN and therefore must have been moved
590      * to another BIN during a split.
591      */

592     private void checkForRelocatedSlots(DatabaseImpl db,
593                                         BINReference binRef,
594                                         UtilizationTracker tracker)
595         throws DatabaseException {
596
597         Iterator JavaDoc iter = binRef.getDeletedKeyIterator();
598         if (iter != null) {
599
600             /* mainKey is only used for dups. */
601             byte[] mainKey = binRef.getKey();
602             boolean isDup = (binRef.getData() != null);
603
604             while (iter.hasNext()) {
605                 Key key = (Key) iter.next();
606
607                 /*
608                  * Lookup the BIN for each deleted key, and compress that BIN
609                  * separately.
610                  */

611                 BIN splitBin = isDup ?
612                     searchForBIN(db, mainKey, key.getKey()) :
613                     searchForBIN(db, key.getKey(), null);
614                 if (splitBin != null) {
615                     BINReference splitBinRef = splitBin.createReference();
616                     splitBinRef.addDeletedKey(key);
617             compressBin(db, splitBin, splitBinRef, tracker);
618                 }
619             }
620         }
621     }
622
623     private boolean isRunnable()
624     throws DatabaseException {
625
626     return true;
627     }
628
629     /**
630      * Search the tree for the BIN or DBIN that corresponds to this
631      * BINReference.
632      *
633      * @param binRef the BINReference that indicates the bin we want.
634      * @return the BIN or DBIN that corresponds to this BINReference. The
635      * node is latched upon return. Returns null if the BIN can't be found.
636      */

637     public BIN searchForBIN(DatabaseImpl db, BINReference binRef)
638         throws DatabaseException {
639
640         return searchForBIN(db, binRef.getKey(), binRef.getData());
641     }
642
643     private BIN searchForBIN(DatabaseImpl db, byte[] mainKey, byte[] dupKey)
644         throws DatabaseException {
645
646         /* Search for this IN */
647         Tree tree = db.getTree();
648         IN in = tree.search
649             (mainKey, SearchType.NORMAL, -1, null, false /*updateGeneration*/);
650
651         /* Couldn't find a BIN, return null */
652         if (in == null) {
653             return null;
654         }
655
656         /* This is not a duplicate, we're done. */
657         if (dupKey == null) {
658             return (BIN) in;
659         }
660
661         /* We need to descend down into a duplicate tree. */
662         DIN duplicateRoot = null;
663         DBIN duplicateBin = null;
664         BIN bin = (BIN) in;
665         try {
666             int index = bin.findEntry(mainKey, false, true);
667             if (index >= 0) {
668                 Node node = null;
669         if (!bin.isEntryKnownDeleted(index)) {
670                     /* If fetchTarget returns null, a deleted LN was cleaned. */
671                     node = bin.fetchTarget(index);
672                 }
673                 if (node == null) {
674             bin.releaseLatch();
675             return null;
676         }
677                 if (node.containsDuplicates()) {
678                     /* It's a duplicate tree. */
679                     duplicateRoot = (DIN) node;
680                     duplicateRoot.latch();
681                     bin.releaseLatch();
682                     duplicateBin = (DBIN) tree.searchSubTree
683                         (duplicateRoot, dupKey, SearchType.NORMAL, -1, null,
684                          false /*updateGeneration*/);
685
686                     return duplicateBin;
687                 } else {
688                     /* We haven't migrated to a duplicate tree yet.
689                      * XXX, isn't this taken care of above? */

690                     return bin;
691                 }
692             } else {
693                 bin.releaseLatch();
694                 return null;
695             }
696         } catch (DatabaseException DBE) {
697             if (bin != null) {
698                 bin.releaseLatchIfOwner();
699             }
700             if (duplicateRoot != null) {
701                 duplicateRoot.releaseLatchIfOwner();
702             }
703
704         /*
705          * FindBugs whines about Redundent comparison to null below, but
706          * for stylistic purposes we'll leave it in.
707          */

708             if (duplicateBin != null) {
709                 duplicateBin.releaseLatchIfOwner();
710             }
711             throw DBE;
712         }
713     }
714
715     /**
716      * Reset per-run counters.
717      */

718     private void resetPerRunCounters() {
719     splitBinsThisRun = 0;
720     dbClosedBinsThisRun = 0;
721     cursorsBinsThisRun = 0;
722     nonEmptyBinsThisRun = 0;
723     processedBinsThisRun = 0;
724     }
725
726     private void accumulatePerRunCounters() {
727     splitBins += splitBinsThisRun;
728     dbClosedBins += dbClosedBinsThisRun;
729     cursorsBins += cursorsBinsThisRun;
730     nonEmptyBins += nonEmptyBinsThisRun;
731     processedBins += processedBinsThisRun;
732     }
733
734     /**
735      * Lazily compress a single BIN. Do not do any pruning. The target IN
736      * should be latched when we enter, and it will be remain latched.
737      */

738     public void lazyCompress(IN in)
739         throws DatabaseException {
740
741         if (!in.isCompressible()) {
742             return;
743         }
744
745         assert in.isLatchOwnerForWrite();
746         
747         /* BIN is latched. */
748         BIN bin = (BIN) in;
749         int nCursors = bin.nCursors();
750         if (nCursors > 0) {
751             /* Cursor prohibit compression. */
752             return;
753         } else {
754             BINReference binRef =
755                 removeCompressibleBinReference(bin.getNodeId());
756             if ((binRef == null) || (!binRef.deletedKeysExist())) {
757                 return;
758             } else {
759
760                 boolean requeued = bin.compress(binRef, false /* canFetch */);
761                 lazyProcessed++;
762
763                 /*
764                  * If this wasn't requeued, but there were deleted keys
765                  * remaining, requeue, so the daemon can handle this. Either
766                  * we must have shuffled some items because of a split, or a
767                  * child was not resident and we couldn't process that entry.
768                  */

769                 if (!requeued && binRef.deletedKeysExist()) {
770                     addBinRefToQueue(binRef, false);
771                     lazySplit++;
772                 } else {
773                     if (bin.getNEntries() == 0) {
774                         addBinRefToQueue(binRef, false);
775                         lazyEmpty++;
776                     }
777                 }
778             }
779         }
780     }
781
782     /*
783      * Find the db and bin for a BINReference.
784      * @return true if the db is open and the target bin is found.
785      */

786     private boolean findDBAndBIN(BINSearch binSearch,
787                                  BINReference binRef,
788                                  DbTree dbTree,
789                                  Map JavaDoc dbCache)
790         throws DatabaseException {
791
792         /* Find the database. */
793         binSearch.db = dbTree.getDb
794             (binRef.getDatabaseId(), lockTimeout, dbCache);
795         if ((binSearch.db == null) ||(binSearch.db.isDeleted())) {
796           /* The db was deleted. Ignore this BIN Ref. */
797             dbClosedBinsThisRun++;
798             return false;
799         }
800
801         /* Perform eviction before each operation. */
802         env.getEvictor().doCriticalEviction(true); // backgroundIO
803

804         /* Find the BIN. */
805         binSearch.bin = searchForBIN(binSearch.db, binRef);
806         if ((binSearch.bin == null) ||
807             binSearch.bin.getNodeId() != binRef.getNodeId()) {
808             /* The BIN may have been split. */
809             if (binSearch.bin != null) {
810                 binSearch.bin.releaseLatch();
811             }
812             splitBinsThisRun++;
813             return false;
814         }
815         
816         return true;
817     }
818
819     /* Struct to return multiple values from findDBAndBIN. */
820     private static class BINSearch {
821         public DatabaseImpl db;
822         public BIN bin;
823     }
824 }
825
Popular Tags