Add a core thread that periodically saves the configuration.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 1 Jul 2011 21:39:00 +0000 (23:39 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 1 Jul 2011 21:39:00 +0000 (23:39 +0200)
All functions that change the configuration of the core or of a local Sone
are now required to call Core.touchConfiguration() to let the core know
that it needs to save the configuration.

12 files changed:
src/main/java/net/pterodactylus/sone/core/Core.java
src/main/java/net/pterodactylus/sone/core/SoneInserter.java
src/main/java/net/pterodactylus/sone/web/EditProfilePage.java
src/main/java/net/pterodactylus/sone/web/FollowSonePage.java
src/main/java/net/pterodactylus/sone/web/OptionsPage.java
src/main/java/net/pterodactylus/sone/web/UnfollowSonePage.java
src/main/java/net/pterodactylus/sone/web/ajax/DeleteProfileFieldAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/FollowSoneAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/LikeAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/MoveProfileFieldAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/UnfollowSoneAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/UnlikeAjaxPage.java

index fb687f8..69332a6 100644 (file)
@@ -53,6 +53,7 @@ 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.config.ConfigurationException;
 import net.pterodactylus.util.logging.Logging;
 import net.pterodactylus.util.number.Numbers;
+import net.pterodactylus.util.service.AbstractService;
 import net.pterodactylus.util.thread.Ticker;
 import net.pterodactylus.util.validation.EqualityValidator;
 import net.pterodactylus.util.validation.IntegerRangeValidator;
 import net.pterodactylus.util.thread.Ticker;
 import net.pterodactylus.util.validation.EqualityValidator;
 import net.pterodactylus.util.validation.IntegerRangeValidator;
@@ -66,7 +67,7 @@ import freenet.keys.FreenetURI;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class Core implements IdentityListener, UpdateListener, SoneProvider, PostProvider, SoneInsertListener {
+public class Core extends AbstractService implements IdentityListener, UpdateListener, SoneProvider, PostProvider, SoneInsertListener {
 
        /**
         * Enumeration for the possible states of a {@link Sone}.
 
        /**
         * Enumeration for the possible states of a {@link Sone}.
@@ -124,10 +125,6 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
        /** The FCP interface. */
        private volatile FcpInterface fcpInterface;
 
        /** The FCP interface. */
        private volatile FcpInterface fcpInterface;
 
-       /** Whether the core has been stopped. */
-       @SuppressWarnings("unused")
-       private volatile boolean stopped;
-
        /** The Sones’ statuses. */
        /* synchronize access on itself. */
        private final Map<Sone, SoneStatus> soneStatuses = new HashMap<Sone, SoneStatus>();
        /** The Sones’ statuses. */
        /* synchronize access on itself. */
        private final Map<Sone, SoneStatus> soneStatuses = new HashMap<Sone, SoneStatus>();
@@ -188,6 +185,9 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
        /** Ticker for threads that mark own elements as known. */
        private Ticker localElementTicker = new Ticker();
 
        /** Ticker for threads that mark own elements as known. */
        private Ticker localElementTicker = new Ticker();
 
+       /** The time the configuration was last touched. */
+       private volatile long lastConfigurationUpdate;
+
        /**
         * Creates a new core.
         *
        /**
         * Creates a new core.
         *
@@ -199,6 +199,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
         *            The identity manager
         */
        public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager) {
         *            The identity manager
         */
        public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager) {
+               super("Sone Core");
                this.configuration = configuration;
                this.freenetInterface = freenetInterface;
                this.identityManager = identityManager;
                this.configuration = configuration;
                this.freenetInterface = freenetInterface;
                this.identityManager = identityManager;
@@ -243,7 +244,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
         */
        public void setConfiguration(Configuration configuration) {
                this.configuration = configuration;
         */
        public void setConfiguration(Configuration configuration) {
                this.configuration = configuration;
-               saveConfiguration();
+               touchConfiguration();
        }
 
        /**
        }
 
        /**
@@ -908,7 +909,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                Sone sone = addLocalSone(ownIdentity);
                sone.getOptions().addBooleanOption("AutoFollow", new DefaultOption<Boolean>(false));
                sone.addFriend("nwa8lHa271k2QvJ8aa0Ov7IHAV-DFOCFgmDt3X6BpCI");
                Sone sone = addLocalSone(ownIdentity);
                sone.getOptions().addBooleanOption("AutoFollow", new DefaultOption<Boolean>(false));
                sone.addFriend("nwa8lHa271k2QvJ8aa0Ov7IHAV-DFOCFgmDt3X6BpCI");
-               saveSone(sone);
+               touchConfiguration();
                return sone;
        }
 
                return sone;
        }
 
@@ -941,7 +942,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                                        for (Sone localSone : getLocalSones()) {
                                                if (localSone.getOptions().getBooleanOption("AutoFollow").get()) {
                                                        localSone.addFriend(sone.getId());
                                        for (Sone localSone : getLocalSones()) {
                                                if (localSone.getOptions().getBooleanOption("AutoFollow").get()) {
                                                        localSone.addFriend(sone.getId());
-                                                       saveSone(localSone);
+                                                       touchConfiguration();
                                                }
                                        }
                                }
                                                }
                                        }
                                }
@@ -1201,7 +1202,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                        if (newSones.remove(sone.getId())) {
                                knownSones.add(sone.getId());
                                coreListenerManager.fireMarkSoneKnown(sone);
                        if (newSones.remove(sone.getId())) {
                                knownSones.add(sone.getId());
                                coreListenerManager.fireMarkSoneKnown(sone);
-                               saveConfiguration();
+                               touchConfiguration();
                        }
                }
        }
                        }
                }
        }
@@ -1353,105 +1354,6 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
        }
 
        /**
        }
 
        /**
-        * Saves the given Sone. This will persist all local settings for the given
-        * Sone, such as the friends list and similar, private options.
-        *
-        * @param sone
-        *            The Sone to save
-        */
-       public synchronized void saveSone(Sone sone) {
-               if (!isLocalSone(sone)) {
-                       logger.log(Level.FINE, "Tried to save non-local Sone: %s", sone);
-                       return;
-               }
-               if (!(sone.getIdentity() instanceof OwnIdentity)) {
-                       logger.log(Level.WARNING, "Local Sone without OwnIdentity found, refusing to save: %s", sone);
-                       return;
-               }
-
-               logger.log(Level.INFO, "Saving Sone: %s", sone);
-               try {
-                       ((OwnIdentity) sone.getIdentity()).setProperty("Sone.LatestEdition", String.valueOf(sone.getLatestEdition()));
-
-                       /* save Sone into configuration. */
-                       String sonePrefix = "Sone/" + sone.getId();
-                       configuration.getLongValue(sonePrefix + "/Time").setValue(sone.getTime());
-                       configuration.getStringValue(sonePrefix + "/LastInsertFingerprint").setValue(soneInserters.get(sone).getLastInsertFingerprint());
-
-                       /* save profile. */
-                       Profile profile = sone.getProfile();
-                       configuration.getStringValue(sonePrefix + "/Profile/FirstName").setValue(profile.getFirstName());
-                       configuration.getStringValue(sonePrefix + "/Profile/MiddleName").setValue(profile.getMiddleName());
-                       configuration.getStringValue(sonePrefix + "/Profile/LastName").setValue(profile.getLastName());
-                       configuration.getIntValue(sonePrefix + "/Profile/BirthDay").setValue(profile.getBirthDay());
-                       configuration.getIntValue(sonePrefix + "/Profile/BirthMonth").setValue(profile.getBirthMonth());
-                       configuration.getIntValue(sonePrefix + "/Profile/BirthYear").setValue(profile.getBirthYear());
-
-                       /* save profile fields. */
-                       int fieldCounter = 0;
-                       for (Field profileField : profile.getFields()) {
-                               String fieldPrefix = sonePrefix + "/Profile/Fields/" + fieldCounter++;
-                               configuration.getStringValue(fieldPrefix + "/Name").setValue(profileField.getName());
-                               configuration.getStringValue(fieldPrefix + "/Value").setValue(profileField.getValue());
-                       }
-                       configuration.getStringValue(sonePrefix + "/Profile/Fields/" + fieldCounter + "/Name").setValue(null);
-
-                       /* save posts. */
-                       int postCounter = 0;
-                       for (Post post : sone.getPosts()) {
-                               String postPrefix = sonePrefix + "/Posts/" + postCounter++;
-                               configuration.getStringValue(postPrefix + "/ID").setValue(post.getId());
-                               configuration.getStringValue(postPrefix + "/Recipient").setValue((post.getRecipient() != null) ? post.getRecipient().getId() : null);
-                               configuration.getLongValue(postPrefix + "/Time").setValue(post.getTime());
-                               configuration.getStringValue(postPrefix + "/Text").setValue(post.getText());
-                       }
-                       configuration.getStringValue(sonePrefix + "/Posts/" + postCounter + "/ID").setValue(null);
-
-                       /* save replies. */
-                       int replyCounter = 0;
-                       for (Reply reply : sone.getReplies()) {
-                               String replyPrefix = sonePrefix + "/Replies/" + replyCounter++;
-                               configuration.getStringValue(replyPrefix + "/ID").setValue(reply.getId());
-                               configuration.getStringValue(replyPrefix + "/Post/ID").setValue(reply.getPost().getId());
-                               configuration.getLongValue(replyPrefix + "/Time").setValue(reply.getTime());
-                               configuration.getStringValue(replyPrefix + "/Text").setValue(reply.getText());
-                       }
-                       configuration.getStringValue(sonePrefix + "/Replies/" + replyCounter + "/ID").setValue(null);
-
-                       /* save post likes. */
-                       int postLikeCounter = 0;
-                       for (String postId : sone.getLikedPostIds()) {
-                               configuration.getStringValue(sonePrefix + "/Likes/Post/" + postLikeCounter++ + "/ID").setValue(postId);
-                       }
-                       configuration.getStringValue(sonePrefix + "/Likes/Post/" + postLikeCounter + "/ID").setValue(null);
-
-                       /* save reply likes. */
-                       int replyLikeCounter = 0;
-                       for (String replyId : sone.getLikedReplyIds()) {
-                               configuration.getStringValue(sonePrefix + "/Likes/Reply/" + replyLikeCounter++ + "/ID").setValue(replyId);
-                       }
-                       configuration.getStringValue(sonePrefix + "/Likes/Reply/" + replyLikeCounter + "/ID").setValue(null);
-
-                       /* save friends. */
-                       int friendCounter = 0;
-                       for (String friendId : sone.getFriends()) {
-                               configuration.getStringValue(sonePrefix + "/Friends/" + friendCounter++ + "/ID").setValue(friendId);
-                       }
-                       configuration.getStringValue(sonePrefix + "/Friends/" + friendCounter + "/ID").setValue(null);
-
-                       /* save options. */
-                       configuration.getBooleanValue(sonePrefix + "/Options/AutoFollow").setValue(sone.getOptions().getBooleanOption("AutoFollow").getReal());
-
-                       configuration.save();
-                       logger.log(Level.INFO, "Sone %s saved.", sone);
-               } catch (ConfigurationException ce1) {
-                       logger.log(Level.WARNING, "Could not save Sone: " + sone, ce1);
-               } catch (WebOfTrustException wote1) {
-                       logger.log(Level.WARNING, "Could not set WoT property for Sone: " + sone, wote1);
-               }
-       }
-
-       /**
         * Creates a new post.
         *
         * @param sone
         * Creates a new post.
         *
         * @param sone
@@ -1526,7 +1428,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                        coreListenerManager.fireNewPostFound(post);
                }
                sone.addPost(post);
                        coreListenerManager.fireNewPostFound(post);
                }
                sone.addPost(post);
-               saveSone(sone);
+               touchConfiguration();
                localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
 
                        /**
                localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
 
                        /**
@@ -1560,7 +1462,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                        markPostKnown(post);
                        knownPosts.remove(post.getId());
                }
                        markPostKnown(post);
                        knownPosts.remove(post.getId());
                }
-               saveSone(post.getSone());
+               touchConfiguration();
        }
 
        /**
        }
 
        /**
@@ -1575,7 +1477,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                        if (newPosts.remove(post.getId())) {
                                knownPosts.add(post.getId());
                                coreListenerManager.fireMarkPostKnown(post);
                        if (newPosts.remove(post.getId())) {
                                knownPosts.add(post.getId());
                                coreListenerManager.fireMarkPostKnown(post);
-                               saveConfiguration();
+                               touchConfiguration();
                        }
                }
        }
                        }
                }
        }
@@ -1666,7 +1568,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                        coreListenerManager.fireNewReplyFound(reply);
                }
                sone.addReply(reply);
                        coreListenerManager.fireNewReplyFound(reply);
                }
                sone.addReply(reply);
-               saveSone(sone);
+               touchConfiguration();
                localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
 
                        /**
                localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
 
                        /**
@@ -1700,7 +1602,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                        knownReplies.remove(reply.getId());
                }
                sone.removeReply(reply);
                        knownReplies.remove(reply.getId());
                }
                sone.removeReply(reply);
-               saveSone(sone);
+               touchConfiguration();
        }
 
        /**
        }
 
        /**
@@ -1715,44 +1617,176 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                        if (newReplies.remove(reply.getId())) {
                                knownReplies.add(reply.getId());
                                coreListenerManager.fireMarkReplyKnown(reply);
                        if (newReplies.remove(reply.getId())) {
                                knownReplies.add(reply.getId());
                                coreListenerManager.fireMarkReplyKnown(reply);
-                               saveConfiguration();
+                               touchConfiguration();
                        }
                }
        }
 
        /**
                        }
                }
        }
 
        /**
+        * Notifies the core that the configuration, either of the core or of a
+        * single local Sone, has changed, and that the configuration should be
+        * saved.
+        */
+       public void touchConfiguration() {
+               lastConfigurationUpdate = System.currentTimeMillis();
+       }
+
+       //
+       // SERVICE METHODS
+       //
+
+       /**
         * Starts the core.
         */
         * Starts the core.
         */
-       public void start() {
+       @Override
+       public void serviceStart() {
                loadConfiguration();
                updateChecker.addUpdateListener(this);
                updateChecker.start();
        }
 
        /**
                loadConfiguration();
                updateChecker.addUpdateListener(this);
                updateChecker.start();
        }
 
        /**
+        * {@inheritDoc}
+        */
+       @Override
+       public void serviceRun() {
+               long lastSaved = System.currentTimeMillis();
+               while (!shouldStop()) {
+                       sleep(1000);
+                       long now = System.currentTimeMillis();
+                       if (shouldStop() || ((lastConfigurationUpdate > lastSaved) && ((now - lastConfigurationUpdate) > 5000))) {
+                               for (Sone localSone : getLocalSones()) {
+                                       saveSone(localSone);
+                               }
+                               saveConfiguration();
+                               lastSaved = now;
+                       }
+               }
+       }
+
+       /**
         * Stops the core.
         */
         * Stops the core.
         */
-       public void stop() {
+       @Override
+       public void serviceStop() {
                synchronized (localSones) {
                        for (SoneInserter soneInserter : soneInserters.values()) {
                                soneInserter.removeSoneInsertListener(this);
                                soneInserter.stop();
                        }
                synchronized (localSones) {
                        for (SoneInserter soneInserter : soneInserters.values()) {
                                soneInserter.removeSoneInsertListener(this);
                                soneInserter.stop();
                        }
-                       for (Sone localSone : localSones.values()) {
-                               saveSone(localSone);
-                       }
                }
                updateChecker.stop();
                updateChecker.removeUpdateListener(this);
                soneDownloader.stop();
                }
                updateChecker.stop();
                updateChecker.removeUpdateListener(this);
                soneDownloader.stop();
-               saveConfiguration();
-               stopped = true;
+       }
+
+       //
+       // PRIVATE METHODS
+       //
+
+       /**
+        * Saves the given Sone. This will persist all local settings for the given
+        * Sone, such as the friends list and similar, private options.
+        *
+        * @param sone
+        *            The Sone to save
+        */
+       private synchronized void saveSone(Sone sone) {
+               if (!isLocalSone(sone)) {
+                       logger.log(Level.FINE, "Tried to save non-local Sone: %s", sone);
+                       return;
+               }
+               if (!(sone.getIdentity() instanceof OwnIdentity)) {
+                       logger.log(Level.WARNING, "Local Sone without OwnIdentity found, refusing to save: %s", sone);
+                       return;
+               }
+
+               logger.log(Level.INFO, "Saving Sone: %s", sone);
+               try {
+                       ((OwnIdentity) sone.getIdentity()).setProperty("Sone.LatestEdition", String.valueOf(sone.getLatestEdition()));
+
+                       /* save Sone into configuration. */
+                       String sonePrefix = "Sone/" + sone.getId();
+                       configuration.getLongValue(sonePrefix + "/Time").setValue(sone.getTime());
+                       configuration.getStringValue(sonePrefix + "/LastInsertFingerprint").setValue(soneInserters.get(sone).getLastInsertFingerprint());
+
+                       /* save profile. */
+                       Profile profile = sone.getProfile();
+                       configuration.getStringValue(sonePrefix + "/Profile/FirstName").setValue(profile.getFirstName());
+                       configuration.getStringValue(sonePrefix + "/Profile/MiddleName").setValue(profile.getMiddleName());
+                       configuration.getStringValue(sonePrefix + "/Profile/LastName").setValue(profile.getLastName());
+                       configuration.getIntValue(sonePrefix + "/Profile/BirthDay").setValue(profile.getBirthDay());
+                       configuration.getIntValue(sonePrefix + "/Profile/BirthMonth").setValue(profile.getBirthMonth());
+                       configuration.getIntValue(sonePrefix + "/Profile/BirthYear").setValue(profile.getBirthYear());
+
+                       /* save profile fields. */
+                       int fieldCounter = 0;
+                       for (Field profileField : profile.getFields()) {
+                               String fieldPrefix = sonePrefix + "/Profile/Fields/" + fieldCounter++;
+                               configuration.getStringValue(fieldPrefix + "/Name").setValue(profileField.getName());
+                               configuration.getStringValue(fieldPrefix + "/Value").setValue(profileField.getValue());
+                       }
+                       configuration.getStringValue(sonePrefix + "/Profile/Fields/" + fieldCounter + "/Name").setValue(null);
+
+                       /* save posts. */
+                       int postCounter = 0;
+                       for (Post post : sone.getPosts()) {
+                               String postPrefix = sonePrefix + "/Posts/" + postCounter++;
+                               configuration.getStringValue(postPrefix + "/ID").setValue(post.getId());
+                               configuration.getStringValue(postPrefix + "/Recipient").setValue((post.getRecipient() != null) ? post.getRecipient().getId() : null);
+                               configuration.getLongValue(postPrefix + "/Time").setValue(post.getTime());
+                               configuration.getStringValue(postPrefix + "/Text").setValue(post.getText());
+                       }
+                       configuration.getStringValue(sonePrefix + "/Posts/" + postCounter + "/ID").setValue(null);
+
+                       /* save replies. */
+                       int replyCounter = 0;
+                       for (Reply reply : sone.getReplies()) {
+                               String replyPrefix = sonePrefix + "/Replies/" + replyCounter++;
+                               configuration.getStringValue(replyPrefix + "/ID").setValue(reply.getId());
+                               configuration.getStringValue(replyPrefix + "/Post/ID").setValue(reply.getPost().getId());
+                               configuration.getLongValue(replyPrefix + "/Time").setValue(reply.getTime());
+                               configuration.getStringValue(replyPrefix + "/Text").setValue(reply.getText());
+                       }
+                       configuration.getStringValue(sonePrefix + "/Replies/" + replyCounter + "/ID").setValue(null);
+
+                       /* save post likes. */
+                       int postLikeCounter = 0;
+                       for (String postId : sone.getLikedPostIds()) {
+                               configuration.getStringValue(sonePrefix + "/Likes/Post/" + postLikeCounter++ + "/ID").setValue(postId);
+                       }
+                       configuration.getStringValue(sonePrefix + "/Likes/Post/" + postLikeCounter + "/ID").setValue(null);
+
+                       /* save reply likes. */
+                       int replyLikeCounter = 0;
+                       for (String replyId : sone.getLikedReplyIds()) {
+                               configuration.getStringValue(sonePrefix + "/Likes/Reply/" + replyLikeCounter++ + "/ID").setValue(replyId);
+                       }
+                       configuration.getStringValue(sonePrefix + "/Likes/Reply/" + replyLikeCounter + "/ID").setValue(null);
+
+                       /* save friends. */
+                       int friendCounter = 0;
+                       for (String friendId : sone.getFriends()) {
+                               configuration.getStringValue(sonePrefix + "/Friends/" + friendCounter++ + "/ID").setValue(friendId);
+                       }
+                       configuration.getStringValue(sonePrefix + "/Friends/" + friendCounter + "/ID").setValue(null);
+
+                       /* save options. */
+                       configuration.getBooleanValue(sonePrefix + "/Options/AutoFollow").setValue(sone.getOptions().getBooleanOption("AutoFollow").getReal());
+
+                       configuration.save();
+                       logger.log(Level.INFO, "Sone %s saved.", sone);
+               } catch (ConfigurationException ce1) {
+                       logger.log(Level.WARNING, "Could not save Sone: " + sone, ce1);
+               } catch (WebOfTrustException wote1) {
+                       logger.log(Level.WARNING, "Could not set WoT property for Sone: " + sone, wote1);
+               }
        }
 
        /**
         * Saves the current options.
         */
        }
 
        /**
         * Saves the current options.
         */
-       public void saveConfiguration() {
+       private void saveConfiguration() {
                synchronized (configuration) {
                        if (storingConfiguration) {
                                logger.log(Level.FINE, "Already storing configuration…");
                synchronized (configuration) {
                        if (storingConfiguration) {
                                logger.log(Level.FINE, "Already storing configuration…");
@@ -1825,10 +1859,6 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
                }
        }
 
                }
        }
 
-       //
-       // PRIVATE METHODS
-       //
-
        /**
         * Loads the configuration.
         */
        /**
         * Loads the configuration.
         */
index d4f53c1..f654d09 100644 (file)
@@ -244,7 +244,7 @@ public class SoneInserter extends AbstractService {
                                        }
                                        sone.setTime(insertTime);
                                        sone.setLatestEdition(finalUri.getEdition());
                                        }
                                        sone.setTime(insertTime);
                                        sone.setLatestEdition(finalUri.getEdition());
-                                       core.saveSone(sone);
+                                       core.touchConfiguration();
                                        success = true;
                                        logger.log(Level.INFO, "Inserted Sone “%s” at %s.", new Object[] { sone.getName(), finalUri });
                                } catch (SoneException se1) {
                                        success = true;
                                        logger.log(Level.INFO, "Inserted Sone “%s” at %s.", new Object[] { sone.getName(), finalUri });
                                } catch (SoneException se1) {
index 52468a3..43dd15b 100644 (file)
@@ -84,7 +84,7 @@ public class EditProfilePage extends SoneTemplatePage {
                                        field.setValue(value);
                                }
                                currentSone.setProfile(profile);
                                        field.setValue(value);
                                }
                                currentSone.setProfile(profile);
-                               webInterface.getCore().saveSone(currentSone);
+                               webInterface.getCore().touchConfiguration();
                                throw new RedirectException("editProfile.html");
                        } else if (request.getHttpRequest().getPartAsStringFailsafe("add-field", 4).equals("true")) {
                                String fieldName = request.getHttpRequest().getPartAsStringFailsafe("field-name", 256).trim();
                                throw new RedirectException("editProfile.html");
                        } else if (request.getHttpRequest().getPartAsStringFailsafe("add-field", 4).equals("true")) {
                                String fieldName = request.getHttpRequest().getPartAsStringFailsafe("field-name", 256).trim();
@@ -92,7 +92,7 @@ public class EditProfilePage extends SoneTemplatePage {
                                        profile.addField(fieldName);
                                        currentSone.setProfile(profile);
                                        fields = profile.getFields();
                                        profile.addField(fieldName);
                                        currentSone.setProfile(profile);
                                        fields = profile.getFields();
-                                       webInterface.getCore().saveSone(currentSone);
+                                       webInterface.getCore().touchConfiguration();
                                        throw new RedirectException("editProfile.html#profile-fields");
                                } catch (IllegalArgumentException iae1) {
                                        templateContext.set("fieldName", fieldName);
                                        throw new RedirectException("editProfile.html#profile-fields");
                                } catch (IllegalArgumentException iae1) {
                                        templateContext.set("fieldName", fieldName);
index 0bf84d7..81225e9 100644 (file)
@@ -56,7 +56,7 @@ public class FollowSonePage extends SoneTemplatePage {
                        for (String soneId : soneIds.split("[ ,]+")) {
                                currentSone.addFriend(soneId);
                        }
                        for (String soneId : soneIds.split("[ ,]+")) {
                                currentSone.addFriend(soneId);
                        }
-                       webInterface.getCore().saveSone(currentSone);
+                       webInterface.getCore().touchConfiguration();
                        throw new RedirectException(returnPage);
                }
        }
                        throw new RedirectException(returnPage);
                }
        }
index 3d1eaad..15bf93d 100644 (file)
@@ -64,7 +64,7 @@ public class OptionsPage extends SoneTemplatePage {
                        if (currentSone != null) {
                                boolean autoFollow = request.getHttpRequest().isPartSet("auto-follow");
                                currentSone.getOptions().getBooleanOption("AutoFollow").set(autoFollow);
                        if (currentSone != null) {
                                boolean autoFollow = request.getHttpRequest().isPartSet("auto-follow");
                                currentSone.getOptions().getBooleanOption("AutoFollow").set(autoFollow);
-                               webInterface.getCore().saveSone(currentSone);
+                               webInterface.getCore().touchConfiguration();
                        }
                        Integer insertionDelay = Numbers.safeParseInteger(request.getHttpRequest().getPartAsStringFailsafe("insertion-delay", 16));
                        if (!preferences.validateInsertionDelay(insertionDelay)) {
                        }
                        Integer insertionDelay = Numbers.safeParseInteger(request.getHttpRequest().getPartAsStringFailsafe("insertion-delay", 16));
                        if (!preferences.validateInsertionDelay(insertionDelay)) {
@@ -112,7 +112,7 @@ public class OptionsPage extends SoneTemplatePage {
                        preferences.setClearOnNextRestart(clearOnNextRestart);
                        boolean reallyClearOnNextRestart = Boolean.parseBoolean(request.getHttpRequest().getPartAsStringFailsafe("really-clear-on-next-restart", 5));
                        preferences.setReallyClearOnNextRestart(reallyClearOnNextRestart);
                        preferences.setClearOnNextRestart(clearOnNextRestart);
                        boolean reallyClearOnNextRestart = Boolean.parseBoolean(request.getHttpRequest().getPartAsStringFailsafe("really-clear-on-next-restart", 5));
                        preferences.setReallyClearOnNextRestart(reallyClearOnNextRestart);
-                       webInterface.getCore().saveConfiguration();
+                       webInterface.getCore().touchConfiguration();
                        if (fieldErrors.isEmpty()) {
                                throw new RedirectException(getPath());
                        }
                        if (fieldErrors.isEmpty()) {
                                throw new RedirectException(getPath());
                        }
index 191d9d4..33b88a1 100644 (file)
@@ -56,7 +56,7 @@ public class UnfollowSonePage extends SoneTemplatePage {
                        for (String soneId : soneIds.split("[ ,]+")) {
                                currentSone.removeFriend(soneId);
                        }
                        for (String soneId : soneIds.split("[ ,]+")) {
                                currentSone.removeFriend(soneId);
                        }
-                       webInterface.getCore().saveSone(currentSone);
+                       webInterface.getCore().touchConfiguration();
                        throw new RedirectException(returnPage);
                }
        }
                        throw new RedirectException(returnPage);
                }
        }
index 383d2d4..4625c13 100644 (file)
@@ -54,7 +54,7 @@ public class DeleteProfileFieldAjaxPage extends JsonPage {
                }
                profile.removeField(field);
                currentSone.setProfile(profile);
                }
                profile.removeField(field);
                currentSone.setProfile(profile);
-               webInterface.getCore().saveSone(currentSone);
+               webInterface.getCore().touchConfiguration();
                return createSuccessJsonObject().put("field", new JsonObject().put("id", field.getId()));
        }
 
                return createSuccessJsonObject().put("field", new JsonObject().put("id", field.getId()));
        }
 
index 1269b41..d82ab1d 100644 (file)
@@ -52,7 +52,7 @@ public class FollowSoneAjaxPage extends JsonPage {
                        return createErrorJsonObject("auth-required");
                }
                currentSone.addFriend(soneId);
                        return createErrorJsonObject("auth-required");
                }
                currentSone.addFriend(soneId);
-               webInterface.getCore().saveSone(currentSone);
+               webInterface.getCore().touchConfiguration();
                return createSuccessJsonObject();
        }
 
                return createSuccessJsonObject();
        }
 
index efd1439..bf87ead 100644 (file)
@@ -55,10 +55,10 @@ public class LikeAjaxPage extends JsonPage {
                }
                if ("post".equals(type)) {
                        currentSone.addLikedPostId(id);
                }
                if ("post".equals(type)) {
                        currentSone.addLikedPostId(id);
-                       webInterface.getCore().saveSone(currentSone);
+                       webInterface.getCore().touchConfiguration();
                } else if ("reply".equals(type)) {
                        currentSone.addLikedReplyId(id);
                } else if ("reply".equals(type)) {
                        currentSone.addLikedReplyId(id);
-                       webInterface.getCore().saveSone(currentSone);
+                       webInterface.getCore().touchConfiguration();
                } else {
                        return createErrorJsonObject("invalid-type");
                }
                } else {
                        return createErrorJsonObject("invalid-type");
                }
index 780e4d1..092c1f7 100644 (file)
@@ -71,7 +71,7 @@ public class MoveProfileFieldAjaxPage extends JsonPage {
                        return createErrorJsonObject("not-possible");
                }
                currentSone.setProfile(profile);
                        return createErrorJsonObject("not-possible");
                }
                currentSone.setProfile(profile);
-               webInterface.getCore().saveSone(currentSone);
+               webInterface.getCore().touchConfiguration();
                return createSuccessJsonObject();
        }
 
                return createSuccessJsonObject();
        }
 
index c2379e8..7f719b7 100644 (file)
@@ -52,7 +52,7 @@ public class UnfollowSoneAjaxPage extends JsonPage {
                        return createErrorJsonObject("auth-required");
                }
                currentSone.removeFriend(soneId);
                        return createErrorJsonObject("auth-required");
                }
                currentSone.removeFriend(soneId);
-               webInterface.getCore().saveSone(currentSone);
+               webInterface.getCore().touchConfiguration();
                return createSuccessJsonObject();
        }
 
                return createSuccessJsonObject();
        }
 
index e5c933d..84b0593 100644 (file)
@@ -55,10 +55,10 @@ public class UnlikeAjaxPage extends JsonPage {
                }
                if ("post".equals(type)) {
                        currentSone.removeLikedPostId(id);
                }
                if ("post".equals(type)) {
                        currentSone.removeLikedPostId(id);
-                       webInterface.getCore().saveSone(currentSone);
+                       webInterface.getCore().touchConfiguration();
                } else if ("reply".equals(type)) {
                        currentSone.removeLikedReplyId(id);
                } else if ("reply".equals(type)) {
                        currentSone.removeLikedReplyId(id);
-                       webInterface.getCore().saveSone(currentSone);
+                       webInterface.getCore().touchConfiguration();
                } else {
                        return createErrorJsonObject("invalid-type");
                }
                } else {
                        return createErrorJsonObject("invalid-type");
                }