Merge branch 'release-0.6.5'
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Core.java
index 765b672..3c99eef 100644 (file)
@@ -49,13 +49,16 @@ import net.pterodactylus.sone.freenet.wot.OwnIdentity;
 import net.pterodactylus.sone.freenet.wot.Trust;
 import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
 import net.pterodactylus.sone.main.SonePlugin;
+import net.pterodactylus.util.collection.Pair;
 import net.pterodactylus.util.config.Configuration;
 import net.pterodactylus.util.config.ConfigurationException;
 import net.pterodactylus.util.logging.Logging;
 import net.pterodactylus.util.number.Numbers;
+import net.pterodactylus.util.thread.Ticker;
 import net.pterodactylus.util.validation.IntegerRangeValidator;
 import net.pterodactylus.util.validation.Validation;
 import net.pterodactylus.util.version.Version;
+import freenet.client.FetchResult;
 import freenet.keys.FreenetURI;
 
 /**
@@ -63,7 +66,7 @@ import freenet.keys.FreenetURI;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class Core implements IdentityListener, UpdateListener {
+public class Core implements IdentityListener, UpdateListener, SoneProvider, PostProvider {
 
        /**
         * Enumeration for the possible states of a {@link Sone}.
@@ -177,6 +180,9 @@ public class Core implements IdentityListener, UpdateListener {
        /** Trusted identities, sorted by own identities. */
        private Map<OwnIdentity, Set<Identity>> trustedIdentities = Collections.synchronizedMap(new HashMap<OwnIdentity, Set<Identity>>());
 
+       /** Ticker for threads that mark own elements as known. */
+       private Ticker localElementTicker = new Ticker();
+
        /**
         * Creates a new core.
         *
@@ -350,6 +356,7 @@ public class Core implements IdentityListener, UpdateListener {
         * @return The Sone with the given ID, or {@code null} if there is no such
         *         Sone
         */
+       @Override
        public Sone getSone(String id, boolean create) {
                if (isLocalSone(id)) {
                        return getLocalSone(id);
@@ -572,6 +579,7 @@ public class Core implements IdentityListener, UpdateListener {
         *            exists, {@code false} to return {@code null}
         * @return The post, or {@code null} if there is no such post
         */
+       @Override
        public Post getPost(String postId, boolean create) {
                synchronized (posts) {
                        Post post = posts.get(postId);
@@ -867,6 +875,14 @@ public class Core implements IdentityListener, UpdateListener {
                                        coreListenerManager.fireRescuingSone(sone);
                                        lockSone(sone);
                                        long edition = sone.getLatestEdition();
+                                       /* find the latest edition the node knows about. */
+                                       Pair<FreenetURI, FetchResult> currentUri = freenetInterface.fetchUri(sone.getRequestUri());
+                                       if (currentUri != null) {
+                                               long currentEdition = currentUri.getLeft().getEdition();
+                                               if (currentEdition > edition) {
+                                                       edition = currentEdition;
+                                               }
+                                       }
                                        while (!stopped && (edition >= 0) && preferences.isSoneRescueMode()) {
                                                logger.log(Level.FINE, "Downloading edition " + edition + "…");
                                                soneDownloader.fetchSone(sone, sone.getRequestUri().setKeyType("SSK").setDocName("Sone-" + edition));
@@ -933,6 +949,7 @@ public class Core implements IdentityListener, UpdateListener {
                                        for (Sone localSone : getLocalSones()) {
                                                if (localSone.getOptions().getBooleanOption("AutoFollow").get()) {
                                                        localSone.addFriend(sone.getId());
+                                                       saveSone(localSone);
                                                }
                                        }
                                }
@@ -1489,7 +1506,7 @@ public class Core implements IdentityListener, UpdateListener {
                        logger.log(Level.FINE, "Tried to create post for non-local Sone: %s", sone);
                        return null;
                }
-               Post post = new Post(sone, time, text);
+               final Post post = new Post(sone, time, text);
                if (recipient != null) {
                        post.setRecipient(recipient);
                }
@@ -1502,6 +1519,16 @@ public class Core implements IdentityListener, UpdateListener {
                }
                sone.addPost(post);
                saveSone(sone);
+               localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @Override
+                       public void run() {
+                               markPostKnown(post);
+                       }
+               }, "Mark " + post + " read.");
                return post;
        }
 
@@ -1622,7 +1649,7 @@ public class Core implements IdentityListener, UpdateListener {
                        logger.log(Level.FINE, "Tried to create reply for non-local Sone: %s", sone);
                        return null;
                }
-               Reply reply = new Reply(sone, post, System.currentTimeMillis(), text);
+               final Reply reply = new Reply(sone, post, System.currentTimeMillis(), text);
                synchronized (replies) {
                        replies.put(reply.getId(), reply);
                }
@@ -1632,6 +1659,16 @@ public class Core implements IdentityListener, UpdateListener {
                }
                sone.addReply(reply);
                saveSone(sone);
+               localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @Override
+                       public void run() {
+                               markReplyKnown(reply);
+                       }
+               }, "Mark " + reply + " read.");
                return reply;
        }
 
@@ -1692,6 +1729,9 @@ public class Core implements IdentityListener, UpdateListener {
                        for (SoneInserter soneInserter : soneInserters.values()) {
                                soneInserter.stop();
                        }
+                       for (Sone localSone : localSones.values()) {
+                               saveSone(localSone);
+                       }
                }
                updateChecker.stop();
                updateChecker.removeUpdateListener(this);
@@ -2023,6 +2063,7 @@ public class Core implements IdentityListener, UpdateListener {
                }
                synchronized (newSones) {
                        newSones.remove(identity.getId());
+                       coreListenerManager.fireSoneRemoved(sone);
                }
        }