Use SHA-256 hashes for fingerprinting.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 3 Feb 2013 12:11:11 +0000 (13:11 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 3 Feb 2013 12:11:11 +0000 (13:11 +0100)
The fingerprint for my Sone was a string that occupied more than 3 MB
in memory alone. That is completely unnecessary.

src/main/java/net/pterodactylus/sone/data/Album.java
src/main/java/net/pterodactylus/sone/data/Image.java
src/main/java/net/pterodactylus/sone/data/Profile.java
src/main/java/net/pterodactylus/sone/data/Sone.java

index c1ae267..7103871 100644 (file)
@@ -32,6 +32,8 @@ import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Collections2;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
 
 /**
  * Container for images that can also contain nested {@link Album}s.
@@ -436,33 +438,33 @@ public class Album implements Fingerprintable {
         */
        @Override
        public String getFingerprint() {
-               StringBuilder fingerprint = new StringBuilder();
-               fingerprint.append("Album(");
-               fingerprint.append("ID(").append(id).append(')');
-               fingerprint.append("Title(").append(title).append(')');
-               fingerprint.append("Description(").append(description).append(')');
+               Hasher hash = Hashing.sha256().newHasher();
+               hash.putString("Album(");
+               hash.putString("ID(").putString(id).putString(")");
+               hash.putString("Title(").putString(title).putString(")");
+               hash.putString("Description(").putString(description).putString(")");
                if (albumImage != null) {
-                       fingerprint.append("AlbumImage(").append(albumImage).append(')');
+                       hash.putString("AlbumImage(").putString(albumImage).putString(")");
                }
 
                /* add nested albums. */
-               fingerprint.append("Albums(");
+               hash.putString("Albums(");
                for (Album album : albums) {
-                       fingerprint.append(album.getFingerprint());
+                       hash.putString(album.getFingerprint());
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
                /* add images. */
-               fingerprint.append("Images(");
+               hash.putString("Images(");
                for (Image image : getImages()) {
                        if (image.isInserted()) {
-                               fingerprint.append(image.getFingerprint());
+                               hash.putString(image.getFingerprint());
                        }
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
-               fingerprint.append(')');
-               return fingerprint.toString();
+               hash.putString(")");
+               return hash.hash().toString();
        }
 
        //
index e50405f..952d540 100644 (file)
@@ -23,6 +23,9 @@ import static com.google.common.base.Preconditions.checkState;
 
 import java.util.UUID;
 
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
 /**
  * Container for image metadata.
  *
@@ -296,13 +299,13 @@ public class Image implements Fingerprintable {
         */
        @Override
        public String getFingerprint() {
-               StringBuilder fingerprint = new StringBuilder();
-               fingerprint.append("Image(");
-               fingerprint.append("ID(").append(id).append(')');
-               fingerprint.append("Title(").append(title).append(')');
-               fingerprint.append("Description(").append(description).append(')');
-               fingerprint.append(')');
-               return fingerprint.toString();
+               Hasher hash = Hashing.sha256().newHasher();
+               hash.putString("Image(");
+               hash.putString("ID(").putString(id).putString(")");
+               hash.putString("Title(").putString(title).putString(")");
+               hash.putString("Description(").putString(description).putString(")");
+               hash.putString(")");
+               return hash.hash().toString();
        }
 
        //
index 57b54c6..5a4fde0 100644 (file)
@@ -26,6 +26,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
 /**
  * A profile stores personal information about a {@link Sone}. All information
  * is optional and can be {@code null}.
@@ -401,37 +404,37 @@ public class Profile implements Fingerprintable {
         */
        @Override
        public String getFingerprint() {
-               StringBuilder fingerprint = new StringBuilder();
-               fingerprint.append("Profile(");
+               Hasher hash = Hashing.sha256().newHasher();
+               hash.putString("Profile(");
                if (firstName != null) {
-                       fingerprint.append("FirstName(").append(firstName).append(')');
+                       hash.putString("FirstName(").putString(firstName).putString(")");
                }
                if (middleName != null) {
-                       fingerprint.append("MiddleName(").append(middleName).append(')');
+                       hash.putString("MiddleName(").putString(middleName).putString(")");
                }
                if (lastName != null) {
-                       fingerprint.append("LastName(").append(lastName).append(')');
+                       hash.putString("LastName(").putString(lastName).putString(")");
                }
                if (birthDay != null) {
-                       fingerprint.append("BirthDay(").append(birthDay).append(')');
+                       hash.putString("BirthDay(").putInt(birthDay).putString(")");
                }
                if (birthMonth != null) {
-                       fingerprint.append("BirthMonth(").append(birthMonth).append(')');
+                       hash.putString("BirthMonth(").putInt(birthMonth).putString(")");
                }
                if (birthYear != null) {
-                       fingerprint.append("BirthYear(").append(birthYear).append(')');
+                       hash.putString("BirthYear(").putInt(birthYear).putString(")");
                }
                if (avatar != null) {
-                       fingerprint.append("Avatar(").append(avatar).append(')');
+                       hash.putString("Avatar(").putString(avatar).putString(")");
                }
-               fingerprint.append("ContactInformation(");
+               hash.putString("ContactInformation(");
                for (Field field : fields) {
-                       fingerprint.append(field.getName()).append('(').append(field.getValue()).append(')');
+                       hash.putString(field.getName()).putString("(").putString(field.getValue()).putString(")");
                }
-               fingerprint.append(")");
-               fingerprint.append(")");
+               hash.putString(")");
+               hash.putString(")");
 
-               return fingerprint.toString();
+               return hash.hash().toString();
        }
 
        /**
index a609982..a3e872b 100644 (file)
@@ -38,6 +38,8 @@ import net.pterodactylus.sone.template.SoneAccessor;
 import net.pterodactylus.util.logging.Logging;
 
 import com.google.common.base.Predicate;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
 
 import freenet.keys.FreenetURI;
 
@@ -915,46 +917,46 @@ public class Sone implements Fingerprintable, Comparable<Sone> {
         */
        @Override
        public synchronized String getFingerprint() {
-               StringBuilder fingerprint = new StringBuilder();
-               fingerprint.append(profile.getFingerprint());
+               Hasher hash = Hashing.sha256().newHasher();
+               hash.putString(profile.getFingerprint());
 
-               fingerprint.append("Posts(");
+               hash.putString("Posts(");
                for (Post post : getPosts()) {
-                       fingerprint.append("Post(").append(post.getId()).append(')');
+                       hash.putString("Post(").putString(post.getId()).putString(")");
                }
-               fingerprint.append(")");
+               hash.putString(")");
 
                List<PostReply> replies = new ArrayList<PostReply>(getReplies());
                Collections.sort(replies, Reply.TIME_COMPARATOR);
-               fingerprint.append("Replies(");
+               hash.putString("Replies(");
                for (PostReply reply : replies) {
-                       fingerprint.append("Reply(").append(reply.getId()).append(')');
+                       hash.putString("Reply(").putString(reply.getId()).putString(")");
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
                List<String> likedPostIds = new ArrayList<String>(getLikedPostIds());
                Collections.sort(likedPostIds);
-               fingerprint.append("LikedPosts(");
+               hash.putString("LikedPosts(");
                for (String likedPostId : likedPostIds) {
-                       fingerprint.append("Post(").append(likedPostId).append(')');
+                       hash.putString("Post(").putString(likedPostId).putString(")");
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
                List<String> likedReplyIds = new ArrayList<String>(getLikedReplyIds());
                Collections.sort(likedReplyIds);
-               fingerprint.append("LikedReplies(");
+               hash.putString("LikedReplies(");
                for (String likedReplyId : likedReplyIds) {
-                       fingerprint.append("Reply(").append(likedReplyId).append(')');
+                       hash.putString("Reply(").putString(likedReplyId).putString(")");
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
-               fingerprint.append("Albums(");
+               hash.putString("Albums(");
                for (Album album : albums) {
-                       fingerprint.append(album.getFingerprint());
+                       hash.putString(album.getFingerprint());
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
-               return fingerprint.toString();
+               return hash.hash().toString();
        }
 
        //