Changeset 2b4f8ed


Ignore:
Timestamp:
Jul 7, 2011 3:19:59 PM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
c4b3551, c7fcef2
Parents:
6818907
Message:
  • Blockfile:
    • Log error on out-of-order spans
    • Log error on corrupt level and discard
    • Fix SkipSpan? non-flush bug causing null levels
    • Add level fixer that repairs nulls and out-of-order levels
    • Fix bug on backwards span construction, not hit in practice
    • Lots of log level changes
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/metanotion/io/RAIFile.java

    r6818907 r2b4f8ed  
    6767        public boolean canWrite() {
    6868                return this.w;
     69        }
     70
     71        /**
     72         *  @since 0.8.8
     73         */
     74        @Override
     75        public String toString() {
     76                if (this.f != null)
     77                        return this.f.getAbsolutePath();
     78                return this.delegate.toString();
    6979        }
    7080
  • core/java/src/net/metanotion/io/block/BlockFile.java

    r6818907 r2b4f8ed  
    123123        }
    124124
     125        /**
     126         *  Run an integrity check on the blockfile and all the skiplists in it
     127         */
    125128        public static void main(String args[]) {
    126129                if (args.length != 1) {
     
    332335                                        flb = new FreeListBlock(file, freeListStart);
    333336                                if(!flb.isEmpty()) {
    334                                         if (log.shouldLog(Log.INFO))
    335                                                 log.info("Alloc from " + flb);
     337                                        if (log.shouldLog(Log.DEBUG))
     338                                                log.debug("Alloc from " + flb);
    336339                                        return flb.takePage();
    337340                                } else {
    338                                         if (log.shouldLog(Log.INFO))
    339                                                 log.info("Alloc returning empty " + flb);
     341                                        if (log.shouldLog(Log.DEBUG))
     342                                                log.debug("Alloc returning empty " + flb);
    340343                                        freeListStart = flb.getNextPage();
    341344                                        writeSuperBlock();
     
    371374                                FreeListBlock.initPage(file, page);
    372375                                writeSuperBlock();
    373                                 if (log.shouldLog(Log.INFO))
    374                                         log.info("Freed page " + page + " as new FLB");
     376                                if (log.shouldLog(Log.DEBUG))
     377                                        log.debug("Freed page " + page + " as new FLB");
    375378                                return;
    376379                        }
     
    380383                                if(flb.isFull()) {
    381384                                        // Make the free page a new FLB
    382                                         if (log.shouldLog(Log.INFO))
    383                                                 log.info("Full: " + flb);
     385                                        if (log.shouldLog(Log.DEBUG))
     386                                                log.debug("Full: " + flb);
    384387                                        FreeListBlock.initPage(file, page);
    385388                                        if(flb.getNextPage() == 0) {
     
    395398                                                writeSuperBlock();
    396399                                        }
    397                                         if (log.shouldLog(Log.INFO))
    398                                                 log.info("Freed page " + page + " to full " + flb);
     400                                        if (log.shouldLog(Log.DEBUG))
     401                                                log.debug("Freed page " + page + " to full " + flb);
    399402                                        return;
    400403                                }
    401404                                flb.addPage(page);
    402                                 if (log.shouldLog(Log.INFO))
    403                                         log.info("Freed page " + page + " to " + flb);
     405                                if (log.shouldLog(Log.DEBUG))
     406                                        log.debug("Freed page " + page + " to " + flb);
    404407                        } catch (IOException ioe) {
    405408                                log.error("Discarding corrupt free list block page " + freeListStart, ioe);
     
    414417        }
    415418
     419        /**
     420         *  If the file is writable, this runs an integrity check and repair
     421         *  on first open.
     422         */
    416423        public BSkipList getIndex(String name, Serializer key, Serializer val) throws IOException {
    417424                // added I2P
     
    423430                if (page == null) { return null; }
    424431                bsl = new BSkipList(spanSize, this, page.intValue(), key, val, true);
     432                if (file.canWrite()) {
     433                        log.info("Checking skiplist " + name + " in blockfile " + file);
     434                        if (bsl.bslck(true, false))
     435                                log.logAlways(Log.WARN, "Repaired skiplist " + name + " in blockfile " + file);
     436                        else
     437                                log.info("No errors in skiplist " + name + " in blockfile " + file);
     438                }
    425439                openIndices.put(name, bsl);
    426440                return bsl;
     
    482496        }
    483497
    484         public void bfck(boolean fix) {
    485                 log.warn("magic bytes " + magicBytes);
    486                 log.warn("fileLen " + fileLen);
    487                 log.warn("freeListStart " + freeListStart);
    488                 log.warn("mounted " + mounted);
    489                 log.warn("spanSize " + spanSize);
    490                 log.warn("Metaindex");
    491                 metaIndex.bslck(true, fix);
     498        /**
     499         *  Run an integrity check on the blockfile and all the skiplists in it
     500         *  @return true if the levels were modified.
     501         */
     502        public boolean bfck(boolean fix) {
     503                log.info("magic bytes " + magicBytes);
     504                log.info("fileLen " + fileLen);
     505                log.info("freeListStart " + freeListStart);
     506                log.info("mounted " + mounted);
     507                log.info("spanSize " + spanSize);
     508                log.info("Metaindex");
     509                log.info("Checking meta index in blockfile " + file);
     510                boolean rv = metaIndex.bslck(fix, true);
     511                if (rv)
     512                        log.warn("Repaired meta index in blockfile " + file);
     513                else
     514                        log.info("No errors in meta index in blockfile " + file);
    492515                int items = 0;
    493516                for (SkipIterator iter = metaIndex.iterator(); iter.hasNext(); ) {
    494517                        String slname = (String) iter.nextKey();
    495518                        Integer page = (Integer) iter.next();
    496                         log.warn("List " + slname + " page " + page);
     519                        log.info("List " + slname + " page " + page);
    497520                        try {
     521                                // This uses IdentityBytes, so the value class won't be right
     522                                //Serializer ser = slname.equals("%%__REVERSE__%%") ? new IntBytes() : new UTF8StringBytes();
    498523                                BSkipList bsl = getIndex(slname, new UTF8StringBytes(), new IdentityBytes());
    499524                                if (bsl == null) {
     
    501526                                        continue;
    502527                                }
    503                                 bsl.bslck(false, fix);
     528                                // The check is now done in getIndex(), no need to do here...
     529                                // but we can't get the return value of the check here.
    504530                                items++;
    505531                        } catch (IOException ioe) {
     
    507533                        }
    508534                }
    509                 log.warn("actual size " + items);
     535                log.info("Checked meta index and " + items + " skiplists");
     536                return rv;
    510537        }
    511538}
  • core/java/src/net/metanotion/io/block/index/BSkipLevels.java

    r6818907 r2b4f8ed  
    3030
    3131import java.io.IOException;
     32import java.util.Comparator;
     33import java.util.Set;
     34import java.util.TreeSet;
    3235
    3336import net.metanotion.io.RandomAccessInterface;
     
    7881                spanPage = bf.file.readUnsignedInt();
    7982                bottom = bsl.spanHash.get(Integer.valueOf(spanPage));
    80                 if (bottom == null)
     83                if (bottom == null) {
    8184                        // FIXME recover better?
    8285                        BlockFile.log.error("No span found in cache???");
     86                        throw new IOException("No span found in cache???");
     87                }
    8388
    8489                this.levels = new BSkipLevels[maxLen];
     
    9196                }
    9297
     98                boolean fail = false;
    9399                for(int i = 0; i < nonNull; i++) {
    94100                        int lp = lps[i];
     
    96102                                levels[i] = bsl.levelHash.get(Integer.valueOf(lp));
    97103                                if(levels[i] == null) {
    98                                         levels[i] = new BSkipLevels(bf, lp, bsl);
    99                                         bsl.levelHash.put(Integer.valueOf(lp), levels[i]);
    100                                 } else {
    101                                 }
     104                                        try {
     105                                                // FIXME this will explode the stack if too big
     106                                                // Redo this without recursion?
     107                                                // Lots of recursion in super to be fixed also...
     108                                                levels[i] = new BSkipLevels(bf, lp, bsl);
     109                                                bsl.levelHash.put(Integer.valueOf(lp), levels[i]);
     110                                        } catch (IOException ioe) {
     111                                                BlockFile.log.error("Corrupt database, bad level " + i +
     112                                                                    " at page " + lp, ioe);
     113                                                levels[i] = null;
     114                                                fail = true;
     115                                                continue;
     116                                        }
     117                                }
     118                                Comparable ourKey = key();
     119                                Comparable nextKey = levels[i].key();
     120                                if (ourKey != null && nextKey != null &&
     121                                    ourKey.compareTo(nextKey) >= 0) {
     122                                        BlockFile.log.warn("Corrupt database, level out of order " + this +
     123                                                            ' ' + print() +
     124                                                            " i = " + i + ' ' + levels[i]);
     125                                        // This will be fixed in blvlfix() via BlockFile.getIndex()
     126                                        //levels[i] = null;
     127                                        //fail = true;
     128                                }
     129                                // TODO also check that the level[] array is not out-of-order
    102130                        } else {
    103131                                if (BlockFile.log.shouldLog(Log.WARN))
    104132                                        BlockFile.log.warn("WTF " + this + " i = " + i + " of " + nonNull + " / " + maxLen + " valid levels but page is zero");
    105133                                levels[i] = null;
    106                         }
     134                                fail = true;
     135                        }
     136                }
     137                if (fail && bf.file.canWrite()) {
     138                        // corruption is actually fixed in blvlfix() via BlockFile.getIndex()
     139                        // after instantiation is complete
     140                        BlockFile.log.error("Repairing corruption of " + this +
     141                                            ' ' + print());
     142                        flush();
     143                        // if the removed levels have no other links to them, they and their data
     144                        // are lost forever, but the alternative is infinite loops / stack overflows
     145                        // in SkipSpan.
    107146                }
    108147        }
     
    145184                        return;
    146185                }
    147                 if (BlockFile.log.shouldLog(Log.INFO))
    148                         BlockFile.log.info("Killing " + this);
     186                if (BlockFile.log.shouldLog(Log.DEBUG))
     187                        BlockFile.log.debug("Killing " + this + ' ' + print(), new Exception());
    149188                isKilled = true;
    150189                bsl.levelHash.remove(Integer.valueOf(levelPage));
     
    159198                        int page = bf.allocPage();
    160199                        BSkipLevels.init(bf, page, bss.page, levels);
    161                         BlockFile.log.info("New BSkipLevels height " + levels + " page " + page);
     200                        if (BlockFile.log.shouldLog(Log.DEBUG))
     201                                BlockFile.log.debug("New BSkipLevels height " + levels + " page " + page);
    162202                        return new BSkipLevels(bf, page, bsl);
    163203                } catch (IOException ioe) { throw new RuntimeException("Error creating database page", ioe); }
    164204        }
    165205
    166         @Override
    167         public void blvlck(boolean fix, int width) {
     206        /**
     207         *  Run an integrity check on the skiplevels from the first,
     208         *  or just fix it if fix == true.
     209         *  Only call from the first level.
     210         *  @return true if the levels were modified.
     211         */
     212        @Override
     213        public boolean blvlck(boolean fix) {
     214                if (fix)
     215                        return blvlfix();
     216                return blvlck(fix, 0, null);
     217        }
     218
     219        /**
     220         *  Fix the levels.
     221         *  Only call from the first level.
     222         *  Primarily to fix nulls in levels caused by previous SkipLevels bug.
     223         *  This should handle dups and loops and out-of-order levels too,
     224         *  but those may cause problems before this in the constructor.
     225         *  This is fast enough to call every time the skiplist is opened.
     226         *  @return true if the levels were modified.
     227         *  @since 0.8.8
     228         */
     229        private boolean blvlfix() {
     230                TreeSet<SkipLevels> lvls = new TreeSet(new LevelComparator());
     231                if (BlockFile.log.shouldLog(Log.DEBUG))
     232                        BlockFile.log.debug("Starting level search");
     233                getAllLevels(this, lvls);
     234                if (BlockFile.log.shouldLog(Log.DEBUG))
     235                        BlockFile.log.debug("Finished level search, found " + lvls.size() + " levels");
     236                if (!this.equals(lvls.last())) {
     237                        BlockFile.log.error("First level is out of order! " + print());
     238                        // TODO switch stack and other fields for the skiplist - hard to test
     239                }
     240                // traverse the levels, back-to-front
     241                boolean rv = false;
     242                SkipLevels after = null;
     243                for (SkipLevels lv : lvls) {
     244                        boolean modified = false;
     245                        if (BlockFile.log.shouldLog(Log.DEBUG))
     246                                BlockFile.log.debug("Checking " + lv.print());
     247                        if (after != null) {
     248                                int min = Math.min(after.levels.length, lv.levels.length);
     249                                for (int i = 0; i < min; i++) {
     250                                        SkipLevels cur = lv.levels[i];
     251                                        if (cur != after) {
     252                                                if (cur != null)
     253                                                        BlockFile.log.warn("Level " + i + " was wrong, fixing for " + lv.print());
     254                                                else
     255                                                        BlockFile.log.warn("Level " + i + " was null, fixing for " + lv.print());
     256                                                lv.levels[i] = after;
     257                                                modified = true;
     258                                        }
     259                                }
     260                        } else {
     261                                // last one
     262                                for (int i = 0; i < lv.levels.length; i++) {
     263                                        if (lv.levels[i] != null) {
     264                                                lv.levels[i] = null;
     265                                                BlockFile.log.warn("Last level " + i + " was non-null, fixing for " + lv.print());
     266                                                modified = true;
     267                                        }
     268                                }
     269                        }
     270                        if (modified) {
     271                                lv.flush();
     272                                rv = true;
     273                        }
     274                        after = lv;
     275                }
     276                if (BlockFile.log.shouldLog(Log.INFO))
     277                        BlockFile.log.info("Checked " + lvls.size() + " levels");
     278                return rv;
     279        }
     280
     281        /**
     282         *  Breadth-first, sortof
     283         *  We assume everything is findable from the root level
     284         *  @param l non-null
     285         *  @param lvlSet out parameter, the result
     286         *  @since 0.8.8
     287         */
     288        private void getAllLevels(SkipLevels l, Set lvlSet) {
     289                if (BlockFile.log.shouldLog(Log.DEBUG))
     290                        BlockFile.log.debug("GAL " + l.print());
     291                // Do level 0 without recursion, on the assumption everything is findable
     292                // from the root
     293                SkipLevels cur = l;
     294                while (cur != null && lvlSet.add(cur)) {
     295                        if (BlockFile.log.shouldLog(Log.DEBUG))
     296                                BlockFile.log.debug("Adding " + cur.print());
     297                        if (!cur.equals(this) && cur.key() == null && BlockFile.log.shouldLog(Log.WARN))
     298                                BlockFile.log.debug("Null KEY!!! " + cur.print());
     299                        cur = cur.levels[0];
     300                }
     301                // If there were no nulls at level 0 in the middle,
     302                // i.e. there are no problems, this won't find anything
     303                for (int i = 1; i < l.levels.length; i++) {
     304                        SkipLevels lv = l.levels[i];
     305                        if (lv != null && !lvlSet.contains(lv))
     306                                getAllLevels(lv, lvlSet);
     307                }
     308        }
     309
     310        /**
     311         *  For sorting levels in blvlfix()
     312         *  Sorts in REVERSE order.
     313         *  @since 0.8.8
     314         */
     315        private static class LevelComparator implements Comparator<SkipLevels> {
     316                public int compare(SkipLevels l, SkipLevels r) {
     317                        Comparable lk = l.key();
     318                        Comparable rk = r.key();
     319                        if (lk == null && rk == null)
     320                                return 0;
     321                        if (lk == null)
     322                                return 1;
     323                        if (rk == null)
     324                                return -1;
     325                        // reverse!
     326                        return rk.compareTo(lk);
     327                }
     328        }
     329
     330        /*
     331         *  Recursively walk through the levels at level 0
     332         *  This needs work.
     333         */
     334        @Override
     335        public boolean blvlck(boolean fix, int width, SkipLevels[] prevLevels) {
    168336                BlockFile.log.warn("    Skip level at width " + width);
    169337                BlockFile.log.warn("        levels " + this.levels.length);
     
    171339                BlockFile.log.warn("        spanPage " + this.spanPage);
    172340                BlockFile.log.warn("        levelPage " + this.levelPage);
     341                SkipLevels higher = null;
    173342                for (int i = levels.length - 1; i >= 0; i--) {
    174343                        if (levels[i] != null) {
    175                                 BlockFile.log.warn("                level " + i + " -> " + levels[i].key() + " ");
     344                                BlockFile.log.info("                level " + i + " -> " + levels[i].key() + " ");
     345                                if (higher != null) {
     346                                        if (higher.key().compareTo(key()) < 0)
     347                                                BlockFile.log.warn("                Higher level has lower key " + higher.key());
     348                                }
    176349                        } else {
    177                                 BlockFile.log.warn("                level " + i + " empty");
    178                         }
     350                                BlockFile.log.info("                level " + i + " empty");
     351                                if (higher != null)
     352                                        BlockFile.log.warn("                Higher level is not empty, key is " + higher.key());
     353                        }
     354                }
     355                if (prevLevels != null) {
     356                        int min = Math.min(prevLevels.length, levels.length);
     357                        for (int i = 0; i < min; i++) {
     358                                if (prevLevels[i] == this) {
     359                                        prevLevels[i] = levels[i];
     360                                } else if (prevLevels[i] != null) {
     361                                        // skipping over us
     362                                        BlockFile.log.warn("                Previous levels is non-null " + prevLevels[i].key() + " but not pointing to us at level " + i);
     363                                        // replace so we only get one error
     364                                        prevLevels[i] = levels[i];
     365                                } else {
     366                                        // dead end in the middle
     367                                        if (levels[i] != null) {
     368                                                BlockFile.log.warn("                Previous levels is null but we are non-null " + levels[i].key() + " at level " + i);
     369                                                // replace so we only get one error
     370                                                prevLevels[i] = levels[i];
     371                                        }
     372                                }
     373                        }
     374                } else {
     375                        prevLevels = new SkipLevels[levels.length];
     376                        System.arraycopy(levels, 0, prevLevels, 0, levels.length);
    179377                }
    180378                if (levels[0] != null)
    181                         levels[0].blvlck(fix, width + 1);
     379                        levels[0].blvlck(fix, width + 1, prevLevels);
     380                return false;
    182381        }
    183382
  • core/java/src/net/metanotion/io/block/index/BSkipList.java

    r6818907 r2b4f8ed  
    225225        }
    226226
    227         public void bslck(boolean isMeta, boolean fix) {
    228                 BlockFile.log.warn("    size " + this.size);
    229                 BlockFile.log.warn("    spans " + this.spanHash.size());
    230                 BlockFile.log.warn("    levels " + this.levelHash.size());
    231                 BlockFile.log.warn("    skipPage " + this.skipPage);
    232                 BlockFile.log.warn("    firstSpanPage " + this.firstSpanPage);
    233                 BlockFile.log.warn("    firstLevelPage " + this.firstLevelPage);
    234                 BlockFile.log.warn("    maxLevels " + this.maxLevels());
    235                 printSL();
    236                 print();
    237                 BlockFile.log.warn("*** Lvlck() ***");
    238                 stack.blvlck(fix, 0);
     227        /**
     228         *  Run an integrity check on the skiplist and all the levels in it
     229         *  @return true if the levels were modified.
     230         */
     231        public boolean bslck(boolean fix, boolean isMeta) {
     232                BlockFile.log.info("    size " + this.size);
     233                BlockFile.log.info("    spans " + this.spanHash.size());
     234                BlockFile.log.info("    levels " + this.levelHash.size());
     235                BlockFile.log.info("    skipPage " + this.skipPage);
     236                BlockFile.log.info("    firstSpanPage " + this.firstSpanPage);
     237                BlockFile.log.info("    firstLevelPage " + this.firstLevelPage);
     238                BlockFile.log.info("    maxLevels " + this.maxLevels());
     239                //printSL();
     240                //print();
     241                //BlockFile.log.info("*** Lvlck() ***");
     242                boolean rv = stack.blvlck(fix);
     243             /****
    239244                int items = 0;
    240245                for (SkipIterator iter = this.iterator(); iter.hasNext(); ) {
     
    242247                        if (isMeta) {
    243248                                int sz = ((Integer) iter.next()).intValue();
    244                                 BlockFile.log.warn("        Item " + key + " page " + sz);
     249                                BlockFile.log.info("        Item " + key.toString() + " page " + sz);
    245250                        } else {
    246251                                String cls= iter.next().getClass().getSimpleName();
    247                                 BlockFile.log.warn("        Item " + key + " class " + cls);
     252                                BlockFile.log.info("        Item " + key.toString() + " class " + cls);
    248253                        }
    249254                        items++;
     
    252257                if (items != this.size)
    253258                        BlockFile.log.warn("****** size mismatch, header = " + this.size + " actual = " + items);
     259              ****/
     260                return rv;
    254261        }
    255262
  • core/java/src/net/metanotion/io/block/index/BSkipSpan.java

    r6818907 r2b4f8ed  
    104104                        return;
    105105                }
    106                 BlockFile.log.info("Killing " + this);
     106                if (BlockFile.log.shouldLog(Log.DEBUG))
     107                        BlockFile.log.debug("Killing " + this);
    107108                isKilled = true;
    108109                try {
     
    227228                                try {
    228229                                        int freed = freeContinuationPages(curNextPage[0]);
    229                                         if (BlockFile.log.shouldLog(Log.INFO))
    230                                                 BlockFile.log.info("Freed " + freed + " continuation pages");
     230                                        if (BlockFile.log.shouldLog(Log.DEBUG))
     231                                                BlockFile.log.debug("Freed " + freed + " continuation pages");
    231232                                } catch (IOException ioe) {
    232233                                        BlockFile.log.error("Error freeing " + this, ioe);
     
    408409                }
    409410
     411                // Go backwards to fill in the rest. This never happens.
    410412                bss = this;
    411413                np = prevPage;
     
    413415                        BSkipSpan temp = bsl.spanHash.get(Integer.valueOf(np));
    414416                        if(temp != null) {
    415                                 bss.next = temp;
     417                                bss.prev = temp;
    416418                                break;
    417419                        }
  • core/java/src/net/metanotion/io/block/index/IBSkipSpan.java

    r6818907 r2b4f8ed  
    278278                        bss.next.next = null;
    279279                        bss.next.prev = bss;
     280                        Comparable previousFirstKey = bss.firstKey;
    280281                        bss = (IBSkipSpan) bss.next;
    281282                       
    282283                        BSkipSpan.loadInit(bss, bf, bsl, np, key, val);
    283284                        bss.loadFirstKey();
     285                        Comparable nextFirstKey = bss.firstKey;
     286                        if (previousFirstKey.compareTo(nextFirstKey) >= 0) {
     287                                // TODO remove, but if we are at the bottom of a level
     288                                // we have to remove the level too, which is a mess
     289                                BlockFile.log.error("Corrupt database, span out of order " + ((BSkipSpan)bss.prev).page +
     290                                                    " first key " + previousFirstKey +
     291                                                    " next page " + bss.page +
     292                                                    " first key " + nextFirstKey);
     293                        }
    284294                        np = bss.nextPage;
    285295                }
    286296
     297                // Go backwards to fill in the rest. This never happens.
    287298                bss = this;
    288299                np = prevPage;
     
    290301                        temp = (IBSkipSpan) bsl.spanHash.get(Integer.valueOf(np));
    291302                        if(temp != null) {
    292                                 bss.next = temp;
     303                                bss.prev = temp;
    293304                                break;
    294305                        }
     
    296307                        bss.prev.next = bss;
    297308                        bss.prev.prev = null;
     309                        Comparable nextFirstKey = bss.firstKey;
    298310                        bss = (IBSkipSpan) bss.prev;
    299311                       
    300312                        BSkipSpan.loadInit(bss, bf, bsl, np, key, val);
    301313                        bss.loadFirstKey();
     314                        Comparable previousFirstKey = bss.firstKey;
     315                        if (previousFirstKey.compareTo(nextFirstKey) >= 0) {
     316                                // TODO remove, but if we are at the bottom of a level
     317                                // we have to remove the level too, which is a mess
     318                                BlockFile.log.error("Corrupt database, span out of order " + bss.page +
     319                                                    " first key " + previousFirstKey +
     320                                                    " next page " + ((BSkipSpan)bss.next).page +
     321                                                    " first key " + nextFirstKey);
     322                        }
    302323                        np = bss.prevPage;
    303324                }
  • core/java/src/net/metanotion/util/skiplist/SkipLevels.java

    r6818907 r2b4f8ed  
    6565        public String print() {
    6666                StringBuilder buf = new StringBuilder(128);
    67                 buf.append("SL: ").append(key()).append(" :: ");
     67                String k = (bottom.nKeys == 0) ? "empty" : (key() != null) ? key().toString() : "null";
     68                buf.append("LVLS: ").append(k).append(" :: ");
    6869                for(int i=0;i<levels.length;i++) {
    6970                        buf.append(i);
     
    181182                                                        }
    182183                                                }
     184                                                this.flush();
    183185                                                if (BlockFile.log.shouldLog(Log.INFO))
    184186                                                        BlockFile.log.info("new Us: " + print());
     
    189191                        }
    190192                }
    191                 if((bottom.nKeys == 0) && (sl.first != bottom)) { this.killInstance(); }
     193                if((bottom.nKeys == 0) && (sl.first != bottom)) {
     194                        // from debugging other problems
     195                        if (res == null) {
     196                                BlockFile.log.warn("WTF killing with no return value " + print());
     197                        } else if (res[1] == null) {
     198                                BlockFile.log.warn("WTF killing with no return value 1 " + print());
     199                        } else if (res[1] != this) {
     200                                BlockFile.log.warn("WTF killing with return value not us " + res[1] + ' ' + print());
     201                        }
     202                        this.killInstance();
     203                }
    192204                return res;
    193205        }
     
    220232                                        }
    221233                                }
    222                                 if (modified)
     234                                if (modified) {
    223235                                        this.flush();
     236                                        if (slvls != null)
     237                                                slvls.flush();
     238                                }
    224239                                return null;
    225240                        }
     
    248263        }
    249264
    250         public void blvlck(boolean fix, int depth) {}
     265        public boolean blvlck(boolean fix) { return false; }
     266        public boolean blvlck(boolean fix, int width, SkipLevels[] prevLevels) { return false; }
    251267}
    252268
  • core/java/src/net/metanotion/util/skiplist/SkipList.java

    r6818907 r2b4f8ed  
    135135        }
    136136
    137         /** dumps all the skip levels */
     137        /**
     138         * dumps all the skip levels
     139         * @deprecated goes to System.out
     140         */
    138141        public void printSL() {
    139142                System.out.println("List size " + size);
     
    141144        }
    142145
    143         /** dumps all the data */
     146        /**
     147         * dumps all the data
     148         * @deprecated goes to System.out
     149         */
    144150        public void print() {
    145151                System.out.println("List size " + size);
  • history.txt

    r6818907 r2b4f8ed  
     12011-07-07 zzz
     2  * Blockfile:
     3    - Log error on out-of-order spans
     4    - Log error on corrupt level and discard
     5    - Fix SkipSpan non-flush bug causing null levels
     6    - Add level fixer that repairs nulls and out-of-order levels
     7    - Fix bug on backwards span construction, not hit in practice
     8    - Lots of log level changes
     9
    1102011-07-06 zzz
    211  * EepGet: Add method to add extra headers to request
  • router/java/src/net/i2p/router/RouterVersion.java

    r6818907 r2b4f8ed  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 5;
     21    public final static long BUILD = 6;
    2222
    2323    /** for example "-test" */
Note: See TracChangeset for help on using the changeset viewer.