From 4f262f61409d33e1f008dd1fdd6d7010dc92302e Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Thu, 21 Apr 2016 14:37:38 +0000
Subject: [PATCH] Addressbook: Use new NamingService API methods in action
 handling - Refactor HostTxtEntry to consolidate properties writing - More
 HostTxtEntry tests - Start of 'remove' entry handling Blockfile: Cleanup
 unused code - Add Iterable interface to SkipList

---
 .../java/src/net/i2p/addressbook/Daemon.java  |  46 ++--
 .../src/net/i2p/addressbook/HostTxtEntry.java | 236 +++++++++---------
 .../net/i2p/addressbook/HostTxtParser.java    |   5 +-
 .../metanotion/io/block/index/BSkipList.java  |   2 +
 .../src/net/metanotion/io/data/LongBytes.java |  59 -----
 .../metanotion/util/skiplist/SkipList.java    |   6 +-
 6 files changed, 158 insertions(+), 196 deletions(-)
 delete mode 100644 core/java/src/net/metanotion/io/data/LongBytes.java

diff --git a/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java b/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java
index aaa2ea9a58..297e6c0e1f 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/Daemon.java
@@ -254,10 +254,10 @@ public class Daemon {
                                     }
                                     String poldname = hprops.getProperty(HostTxtEntry.PROP_OLDNAME);
                                     if (poldname != null) {
-                                        Destination pod = router.lookup(poldname);
+                                        List<Destination> pod = router.lookupAll(poldname);
                                         if (pod == null) {
                                             // we didn't have the old one, so we'll add the new one
-                                        } else if (pod.equals(dest)) {
+                                        } else if (pod.contains(dest)) {
                                             // checks out, so we'll add the new one
                                         } else {
                                             // mismatch, disallow
@@ -297,10 +297,10 @@ public class Daemon {
                                             continue;
                                         }
                                         Destination pod = new Destination(polddest);
-                                        Destination pod2 = router.lookup(poldname);
+                                        List<Destination> pod2 = router.lookupAll(poldname);
                                         if (pod2 == null) {
                                             // we didn't have the old name
-                                        } else if (pod.equals(pod2)) {
+                                        } else if (pod2.contains(pod)) {
                                             // checks out, so verify the inner sig
                                             if (!he.hasValidInnerSig()) {
                                                 if (log != null)
@@ -330,6 +330,8 @@ public class Daemon {
                                     }
                                 } else if (action.equals(HostTxtEntry.ACTION_CHANGEDEST)) {
                                     // change destination on an existing entry
+                                    // This removes all previous destinations under that hostname,
+                                    // is this what we want?
                                     String polddest = hprops.getProperty(HostTxtEntry.PROP_OLDDEST);
                                     if (polddest != null) {
                                         Destination pod = new Destination(polddest);
@@ -369,20 +371,22 @@ public class Daemon {
                                     }
                                 } else if (action.equals(HostTxtEntry.ACTION_CHANGENAME)) {
                                     // Delete old name, replace with new
+                                    // This removes all previous destinations under that hostname,
+                                    // is this what we want?
                                     if (isKnown) {
                                         old++;
                                         continue;
                                     }
                                     String poldname = hprops.getProperty(HostTxtEntry.PROP_OLDNAME);
                                     if (poldname != null) {
-                                        Destination pod = router.lookup(poldname);
+                                        List<Destination> pod = router.lookupAll(poldname);
                                         if (pod == null) {
                                             // we didn't have the old name
-                                        } else if (pod.equals(dest)) {
+                                        } else if (pod.contains(dest)) {
                                             // checks out, so we'll delete it
                                             if (knownNames != null)
                                                 knownNames.remove(poldname);
-                                            boolean success = router.remove(poldname);
+                                            boolean success = router.remove(poldname, dest);
                                             if (success)
                                                 deleted++;
                                             if (log != null) {
@@ -399,7 +403,7 @@ public class Daemon {
                                             if (published != null) {
                                                 if (publishedNS == null)
                                                     publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath());
-                                                success = publishedNS.remove(poldname);
+                                                success = publishedNS.remove(poldname, dest);
                                                 if (log != null && !success)
                                                     log.append("Remove from published address book " + published.getAbsolutePath() + " failed for " + poldname);
                                             }
@@ -431,11 +435,11 @@ public class Daemon {
                                     String poldname = hprops.getProperty(HostTxtEntry.PROP_NAME);
                                     if (polddest != null && poldname != null) {
                                         Destination pod = new Destination(polddest);
-                                        Destination pod2 = router.lookup(poldname);
-                                        if (pod.equals(pod2)) {
-                                            if (knownNames != null)
+                                        List<Destination> pod2 = router.lookupAll(poldname);
+                                        if (pod2 != null && pod2.contains(pod)) {
+                                            if (knownNames != null && pod2.size() == 1)
                                                 knownNames.remove(poldname);
-                                            boolean success = router.remove(poldname);
+                                            boolean success = router.remove(poldname, pod);
                                             if (success)
                                                 deleted++;
                                             if (log != null) {
@@ -452,7 +456,7 @@ public class Daemon {
                                             if (published != null) {
                                                 if (publishedNS == null)
                                                     publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath());
-                                                success = publishedNS.remove(poldname);
+                                                success = publishedNS.remove(poldname, pod);
                                                 if (log != null && !success)
                                                     log.append("Remove from published address book " + published.getAbsolutePath() + " failed for " + poldname);
                                             }
@@ -485,11 +489,11 @@ public class Daemon {
                                         Destination pod = new Destination(polddest);
                                         String poldname = hprops.getProperty(HostTxtEntry.PROP_NAME);
                                         if (poldname != null) {
-                                            Destination pod2 = router.lookup(poldname);
-                                            if (pod.equals(pod2)) {
+                                            List<Destination> pod2 = router.lookupAll(poldname);
+                                            if (pod2 != null && pod2.contains(pod)) {
                                                 if (knownNames != null)
                                                     knownNames.remove(poldname);
-                                                boolean success = router.remove(poldname);
+                                                boolean success = router.remove(poldname, pod);
                                                 if (success)
                                                     deleted++;
                                                 if (log != null) {
@@ -506,7 +510,7 @@ public class Daemon {
                                                 if (published != null) {
                                                     if (publishedNS == null)
                                                         publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath());
-                                                    success = publishedNS.remove(poldname);
+                                                    success = publishedNS.remove(poldname, pod);
                                                     if (log != null && !success)
                                                         log.append("Remove from published address book " + published.getAbsolutePath() + " failed for " + poldname);
                                                 }
@@ -530,12 +534,12 @@ public class Daemon {
                                                 break;
                                             rev2 = rev;
                                             // forward check in case hash collision or something
-                                            Destination fwd = router.lookup(rev);
-                                            if (!pod.equals(fwd))
+                                            List<Destination> fwd = router.lookupAll(rev);
+                                            if (!fwd.contains(pod))
                                                 break;  // can't go around again, fail
                                             if (knownNames != null)
                                                 knownNames.remove(rev);
-                                            boolean success = router.remove(rev);
+                                            boolean success = router.remove(rev, pod);
                                             if (success)
                                                 deleted++;
                                             if (log != null) {
@@ -552,7 +556,7 @@ public class Daemon {
                                             if (published != null) {
                                                 if (publishedNS == null)
                                                     publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath());
-                                                success = publishedNS.remove(rev);
+                                                success = publishedNS.remove(rev, pod);
                                                 if (log != null && !success)
                                                     log.append("Remove from published address book " + published.getAbsolutePath() + " failed for " + rev);
                                             }
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtEntry.java b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtEntry.java
index f1934cc3c7..9f0e0a37d6 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtEntry.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtEntry.java
@@ -2,6 +2,8 @@ package net.i2p.addressbook;
 
 import java.io.BufferedWriter;
 import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.util.Map;
 
 import net.i2p.crypto.DSAEngine;
@@ -17,8 +19,10 @@ import net.i2p.util.OrderedProperties;
 import java.io.File;
 import java.io.OutputStreamWriter;
 import java.io.StringWriter;
+import net.i2p.data.Base32;
 import net.i2p.data.PrivateKeyFile;
 import net.i2p.data.SigningPrivateKey;
+import net.i2p.util.RandomSource;
 
 
 /**
@@ -97,7 +101,7 @@ class HostTxtEntry {
      * @param line part after the #!
      * @throws IllegalArgumentException on dup key and other errors
      */
-    private OrderedProperties parseProps(String line) throws IllegalArgumentException {
+    private static OrderedProperties parseProps(String line) throws IllegalArgumentException {
         line = line.trim();
         OrderedProperties rv = new OrderedProperties();
         String[] entries = DataHelper.split(line, "#");
@@ -115,27 +119,58 @@ class HostTxtEntry {
         return rv;
     }
 
+    /**
+     * Write as a standard line name=dest[#!k1=v1#k2=v2...]
+     * Includes newline.
+     */
     public void write(BufferedWriter out) throws IOException {
         out.write(name);
         out.write(KV_SEPARATOR);
         out.write(dest);
-        if (props != null && props.size() > 0) {
-            boolean started = false;
-            for (Map.Entry<Object, Object> e : props.entrySet()) {
-                if (started) {
-                    out.write(PROP_SEPARATOR);
-                } else {
-                    started = true;
-                    out.write(PROPS_SEPARATOR);
-                }
-                String k = (String) e.getKey();
-                String v = (String) e.getValue();
-                out.write(k);
-                out.write(KV_SEPARATOR);
-                out.write(v);
+        writeProps(out, false, false);
+        out.newLine();
+    }
+
+    /**
+     * Write as a "remove" line #!olddest=dest#oldname=name#k1=v1#k2=v2...]
+     * Includes newline.
+     * Must have been constructed with non-null properties.
+     */
+    public void writeRemove(BufferedWriter out) throws IOException {
+        if (props == null)
+            throw new IllegalStateException();
+        props.setProperty(PROP_OLDNAME, name);
+        props.setProperty(PROP_OLDDEST, dest);
+        writeProps(out, false, false);
+        out.newLine();
+        props.remove(PROP_OLDNAME);
+        props.remove(PROP_OLDDEST);
+    }
+
+    /**
+     * Write the props part (if any) only, without newline
+     */
+    private void writeProps(Writer out, boolean omitSig, boolean omitOldSig) throws IOException {
+        if (props == null)
+            return;
+        boolean started = false;
+        for (Map.Entry<Object, Object> e : props.entrySet()) {
+            String k = (String) e.getKey();
+            if (omitSig && k.equals(PROP_SIG))
+                continue;
+            if (omitOldSig && k.equals(PROP_OLDSIG))
+                continue;
+            if (started) {
+                out.write(PROP_SEPARATOR);
+            } else {
+                started = true;
+                out.write(PROPS_SEPARATOR);
             }
+            String v = (String) e.getValue();
+            out.write(k);
+            out.write(KV_SEPARATOR);
+            out.write(v);
         }
-        out.newLine();
     }
 
     /**
@@ -146,34 +181,19 @@ class HostTxtEntry {
             return false;
         if (!isValidated) {
             isValidated = true;
-            StringBuilder buf = new StringBuilder(1024);
-            String sig = null;
+            StringWriter buf = new StringWriter(1024);
+            String sig = props.getProperty(PROP_SIG);
+            if (sig == null)
+                return false;
             buf.append(name);
             buf.append(KV_SEPARATOR);
             buf.append(dest);
-            boolean started = false;
-            for (Map.Entry<Object, Object> e : props.entrySet()) {
-                String k = (String) e.getKey();
-                String v = (String) e.getValue();
-                if (k.equals(PROP_SIG)) {
-                    if (sig != null)
-                        return false;
-                    sig = v;
-                    // remove from the written data
-                    continue;
-                }
-                if (started) {
-                    buf.append(PROP_SEPARATOR);
-                } else {
-                    started = true;
-                    buf.append(PROPS_SEPARATOR);
-                }
-                buf.append(k);
-                buf.append(KV_SEPARATOR);
-                buf.append(v);
-            }
-            if (sig == null)
+            try {
+                writeProps(buf, true, false);
+            } catch (IOException ioe) {
+                // won't happen
                 return false;
+            }
             byte[] sdata = Base64.decode(sig);
             if (sdata == null)
                 return false;
@@ -207,43 +227,20 @@ class HostTxtEntry {
         boolean rv = false;
         // don't cache result
         if (true) {
-            StringBuilder buf = new StringBuilder(1024);
-            String sig = null;
-            String olddest = null;
+            StringWriter buf = new StringWriter(1024);
+            String sig = props.getProperty(PROP_OLDSIG);
+            String olddest = props.getProperty(PROP_OLDDEST);
+            if (sig == null || olddest == null)
+                return false;
             buf.append(name);
             buf.append(KV_SEPARATOR);
             buf.append(dest);
-            boolean started = false;
-            for (Map.Entry<Object, Object> e : props.entrySet()) {
-                String k = (String) e.getKey();
-                String v = (String) e.getValue();
-                if (k.equals(PROP_SIG)) {
-                    continue;
-                }
-                if (k.equals(PROP_OLDSIG)) {
-                    if (sig != null)
-                        return false;
-                    sig = v;
-                    // remove from the written data
-                    continue;
-                }
-                if (k.equals(PROP_OLDDEST)) {
-                    if (olddest != null)
-                        return false;
-                    olddest = v;
-                }
-                if (started) {
-                    buf.append(PROP_SEPARATOR);
-                } else {
-                    started = true;
-                    buf.append(PROPS_SEPARATOR);
-                }
-                buf.append(k);
-                buf.append(KV_SEPARATOR);
-                buf.append(v);
-            }
-            if (sig == null || olddest == null)
+            try {
+                writeProps(buf, true, true);
+            } catch (IOException ioe) {
+                // won't happen
                 return false;
+            }
             byte[] sdata = Base64.decode(sig);
             if (sdata == null)
                 return false;
@@ -309,25 +306,16 @@ class HostTxtEntry {
     private void signIt(SigningPrivateKey spk, String sigprop) {
         if (props == null)
             throw new IllegalStateException();
-        StringBuilder buf = new StringBuilder(1024);
+        if (props.containsKey(sigprop))
+            throw new IllegalStateException();
+        StringWriter buf = new StringWriter(1024);
         buf.append(name);
         buf.append(KV_SEPARATOR);
         buf.append(dest);
-        boolean started = false;
-        for (Map.Entry<Object, Object> e : props.entrySet()) {
-            String k = (String) e.getKey();
-            String v = (String) e.getValue();
-            if (k.equals(sigprop))
-                throw new IllegalStateException();
-            if (started) {
-                buf.append(PROP_SEPARATOR);
-            } else {
-                started = true;
-                buf.append(PROPS_SEPARATOR);
-            }
-            buf.append(k);
-            buf.append(KV_SEPARATOR);
-            buf.append(v);
+        try {
+            writeProps(buf, false, false);
+        } catch (IOException ioe) {
+            throw new IllegalStateException(ioe);
         }
         Signature s = DSAEngine.getInstance().sign(DataHelper.getUTF8(buf.toString()), spk);
         if (s == null)
@@ -336,34 +324,54 @@ class HostTxtEntry {
     }
 
     public static void main(String[] args) throws Exception {
+        int astart = 0;
+        if (args.length > 0 && args[0].equals("-i"))
+            astart++;
+        OrderedProperties props = new OrderedProperties();
+        for (int i = astart; i < args.length; i++) {
+            int eq = args[i].indexOf("=");
+            props.setProperty(args[i].substring(0, eq), args[i].substring(eq + 1));
+        }
+        props.setProperty("zzzz", "zzzzzzzzzzzzzzz");
         // outer
         File f = new File("tmp-eepPriv.dat");
-        // inner
-        File f2 = new File("tmp-eepPriv2.dat");
         PrivateKeyFile pkf = new PrivateKeyFile(f);
-        PrivateKeyFile pkf2 = new PrivateKeyFile(f2);
         pkf.createIfAbsent(SigType.EdDSA_SHA512_Ed25519);
-        pkf2.createIfAbsent(SigType.DSA_SHA1);
-        OrderedProperties props = new OrderedProperties();
-        props.setProperty("c", "ccccccccccc");
-        props.setProperty("a", "aaaa");
-        props.setProperty(PROP_OLDDEST, pkf2.getDestination().toBase64());
-        HostTxtEntry he = new HostTxtEntry("foo.i2p", pkf.getDestination().toBase64(), props);
+        f.delete();
+        PrivateKeyFile pkf2;
+        if (astart != 0) {
+            // inner
+            File f2 = new File("tmp-eepPriv2.dat");
+            pkf2 = new PrivateKeyFile(f2);
+            pkf2.createIfAbsent(SigType.DSA_SHA1);
+            f2.delete();
+            props.setProperty(PROP_OLDDEST, pkf2.getDestination().toBase64());
+        } else {
+            pkf2 = null;
+        }
+        byte[] rand = new byte[5];
+        RandomSource.getInstance().nextBytes(rand);
+        String host = Base32.encode(rand) + ".i2p";
+        HostTxtEntry he = new HostTxtEntry(host, pkf.getDestination().toBase64(), props);
         BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
-        out.write("Before signing:\n");
-        he.write(out);
-        out.flush();
+        //out.write("Before signing:\n");
+        //he.write(out);
+        //out.flush();
         SigningPrivateKey priv = pkf.getSigningPrivKey();
-        SigningPrivateKey priv2 = pkf2.getSigningPrivKey();
-        he.signInner(priv2);
-        out.write("After signing inner:\n");
-        he.write(out);
+        if (astart != 0) {
+            SigningPrivateKey priv2 = pkf2.getSigningPrivKey();
+            he.signInner(priv2);
+            //out.write("After signing inner:\n");
+            //he.write(out);
+        }
         he.sign(priv);
-        out.write("After signing:\n");
+        //out.write("After signing:\n");
         he.write(out);
         out.flush();
-        System.out.println("Orig has valid inner sig? " + he.hasValidInnerSig());
-        System.out.println("Orig has valid sig? " + he.hasValidSig());
+        if (astart > 0 && !he.hasValidInnerSig())
+            throw new IllegalStateException("Inner fail 1");
+        if (!he.hasValidSig())
+            throw new IllegalStateException("Outer fail 1");
         // now create 2nd, read in
         StringWriter sw = new StringWriter(1024);
         BufferedWriter buf = new BufferedWriter(sw);
@@ -371,10 +379,12 @@ class HostTxtEntry {
         buf.flush();
         String line = sw.toString();
         line = line.substring(line.indexOf(PROPS_SEPARATOR) + 2);
-        HostTxtEntry he2 = new HostTxtEntry("foo.i2p", pkf.getDestination().toBase64(), line);
-        System.out.println("Dupl. has valid inner sig? " + he2.hasValidInnerSig());
-        System.out.println("Dupl. has valid sig? " + he2.hasValidSig());
-        f.delete();
-        f2.delete();
+        HostTxtEntry he2 = new HostTxtEntry(host, pkf.getDestination().toBase64(), line);
+        if (astart > 0 && !he2.hasValidInnerSig())
+            throw new IllegalStateException("Inner fail 2");
+        if (!he2.hasValidSig())
+            throw new IllegalStateException("Outer fail 2");
+        //out.write("Test passed\n");
+        //out.flush();
     }
 }
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java
index f2c2df1491..92bbce817a 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/HostTxtParser.java
@@ -217,7 +217,10 @@ class HostTxtParser {
         for (HostTxtEntry e : map.values()) {
             System.out.println("Host: " + e.getName() +
                                "\nDest: " + e.getDest() +
-                               "\nValid? " + e.hasValidSig());
+                               "\nAction: " + (e.getProps() != null ? e.getProps().getProperty("action") : "(none)") +
+                               "\nValid Inner? " + e.hasValidInnerSig() +
+                               "\nValid? " + e.hasValidSig() +
+                               '\n');
         }
     }
 
diff --git a/core/java/src/net/metanotion/io/block/index/BSkipList.java b/core/java/src/net/metanotion/io/block/index/BSkipList.java
index 5cb9c84bc0..70990a0e8f 100644
--- a/core/java/src/net/metanotion/io/block/index/BSkipList.java
+++ b/core/java/src/net/metanotion/io/block/index/BSkipList.java
@@ -206,6 +206,7 @@ public class BSkipList<K extends Comparable<? super K>, V> extends SkipList<K, V
 		return new IBSkipIterator<K, V>(first, 0);
 	}
 
+/****
 	@Override
 	public SkipIterator<K, V> min() {
 		return iterator();
@@ -218,6 +219,7 @@ public class BSkipList<K extends Comparable<? super K>, V> extends SkipList<K, V
 		SkipSpan<K, V> ss = stack.getEnd();
 		return new IBSkipIterator<K, V>(ss, ss.nKeys - 1);
 	}
+****/
 
 	@Override
 	public SkipIterator<K, V> find(K key) {
diff --git a/core/java/src/net/metanotion/io/data/LongBytes.java b/core/java/src/net/metanotion/io/data/LongBytes.java
deleted file mode 100644
index cc1ed3c582..0000000000
--- a/core/java/src/net/metanotion/io/data/LongBytes.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-Copyright (c) 2006, Matthew Estes
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-	* Neither the name of Metanotion Software nor the names of its
-contributors may be used to endorse or promote products derived from this
-software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-package net.metanotion.io.data;
-
-import net.metanotion.io.Serializer;
-
-public class LongBytes implements Serializer<Long> {
-	public byte[] getBytes(Long o) {
-		byte[] b = new byte[8];
-		long v = o.longValue();
- 		b[0] = (byte)(0xff & (v >> 56));
-		b[1] = (byte)(0xff & (v >> 48));
- 		b[2] = (byte)(0xff & (v >> 40));
- 		b[3] = (byte)(0xff & (v >> 32));
- 		b[4] = (byte)(0xff & (v >> 24));
- 		b[5] = (byte)(0xff & (v >> 16));
-		b[6] = (byte)(0xff & (v >>  8));
- 		b[7] = (byte)(0xff & v);
- 		return b;
-	}
-
-	public Long construct(byte[] b) {
-		long v =(((long)(b[0] & 0xff) << 56) |
-				 ((long)(b[1] & 0xff) << 48) |
-				 ((long)(b[2] & 0xff) << 40) |
-				 ((long)(b[3] & 0xff) << 32) |
-				 ((long)(b[4] & 0xff) << 24) |
-				 ((long)(b[5] & 0xff) << 16) |
-				 ((long)(b[6] & 0xff) <<  8) |
-				 (b[7] & 0xff));
-		return Long.valueOf(v);
-	}
-}
diff --git a/core/java/src/net/metanotion/util/skiplist/SkipList.java b/core/java/src/net/metanotion/util/skiplist/SkipList.java
index bb4226d780..e7c386cb5c 100644
--- a/core/java/src/net/metanotion/util/skiplist/SkipList.java
+++ b/core/java/src/net/metanotion/util/skiplist/SkipList.java
@@ -35,7 +35,7 @@ import net.i2p.util.RandomSource;
 
 //import net.metanotion.io.block.BlockFile;
 
-public class SkipList<K extends Comparable<? super K>, V> implements Flushable {
+public class SkipList<K extends Comparable<? super K>, V> implements Flushable, Iterable<V> {
 	/** the probability of each next higher level */
 	protected static final int P = 2;
 	private static final int MIN_SLOTS = 4;
@@ -151,6 +151,7 @@ public class SkipList<K extends Comparable<? super K>, V> implements Flushable {
 	 * dumps all the data
 	 * @deprecated goes to System.out
 	 */
+	@Deprecated
 	public void print() {
 		System.out.println("List size " + size);
 		System.out.println(first.print());
@@ -163,12 +164,14 @@ public class SkipList<K extends Comparable<? super K>, V> implements Flushable {
 
 	public SkipIterator<K, V> iterator() { return new SkipIterator<K, V>(first, 0); }
 
+/****
 	public SkipIterator<K, V> min() { return new SkipIterator<K, V>(first, 0); }
 
 	public SkipIterator<K, V> max() {
 		SkipSpan<K, V> ss = stack.getEnd();
 		return new SkipIterator<K, V>(ss, ss.nKeys - 1);
 	}
+****/
 
 	/** @return an iterator where nextKey() is the first one greater than or equal to 'key' */
 	public SkipIterator<K, V> find(K key) {
@@ -178,7 +181,6 @@ public class SkipList<K extends Comparable<? super K>, V> implements Flushable {
 		return new SkipIterator<K, V>(ss, search[0]);
 	}
 
-
 	// Levels adjusted to guarantee O(log n) search
 	// This is expensive proportional to the number of spans.
 	public void balance() {
-- 
GitLab