X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FCore.java;h=c8d75881993c1ba74bc593d4cfcdc2fb15f72fb0;hb=dcd855a3a703fcf8adea143132f4b40a370fc3b6;hp=fb687f871ae9deb6b4770e6e6a2e60d666f2b2b9;hpb=6ca0a375e32d42c68b7c84222d66a049dff192f3;p=Sone.git
diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java
index fb687f8..c8d7588 100644
--- a/src/main/java/net/pterodactylus/sone/core/Core.java
+++ b/src/main/java/net/pterodactylus/sone/core/Core.java
@@ -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.service.AbstractService;
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 David âBombeâ Roden
*/
-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}.
@@ -124,10 +125,6 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
/** 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 soneStatuses = new HashMap();
@@ -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();
+ /** The time the configuration was last touched. */
+ private volatile long lastConfigurationUpdate;
+
/**
* 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) {
+ super("Sone Core");
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;
- saveConfiguration();
+ touchConfiguration();
}
/**
@@ -908,7 +909,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
Sone sone = addLocalSone(ownIdentity);
sone.getOptions().addBooleanOption("AutoFollow", new DefaultOption(false));
sone.addFriend("nwa8lHa271k2QvJ8aa0Ov7IHAV-DFOCFgmDt3X6BpCI");
- saveSone(sone);
+ touchConfiguration();
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());
- 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);
- saveConfiguration();
+ touchConfiguration();
}
}
}
@@ -1221,6 +1222,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
/* initialize options. */
sone.getOptions().addBooleanOption("AutoFollow", new DefaultOption(false));
+ sone.getOptions().addBooleanOption("EnableSoneInsertNotifications", new DefaultOption(false));
/* load Sone. */
String sonePrefix = "Sone/" + sone.getId();
@@ -1323,6 +1325,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
/* load options. */
sone.getOptions().getBooleanOption("AutoFollow").set(configuration.getBooleanValue(sonePrefix + "/Options/AutoFollow").getValue(null));
+ sone.getOptions().getBooleanOption("EnableSoneInsertNotifications").set(configuration.getBooleanValue(sonePrefix + "/Options/EnableSoneInsertNotifications").getValue(null));
/* if weâre still here, Sone was loaded successfully. */
synchronized (sone) {
@@ -1353,105 +1356,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
@@ -1526,7 +1430,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
coreListenerManager.fireNewPostFound(post);
}
sone.addPost(post);
- saveSone(sone);
+ touchConfiguration();
localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
/**
@@ -1560,7 +1464,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
markPostKnown(post);
knownPosts.remove(post.getId());
}
- saveSone(post.getSone());
+ touchConfiguration();
}
/**
@@ -1575,7 +1479,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
if (newPosts.remove(post.getId())) {
knownPosts.add(post.getId());
coreListenerManager.fireMarkPostKnown(post);
- saveConfiguration();
+ touchConfiguration();
}
}
}
@@ -1666,7 +1570,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
coreListenerManager.fireNewReplyFound(reply);
}
sone.addReply(reply);
- saveSone(sone);
+ touchConfiguration();
localElementTicker.registerEvent(System.currentTimeMillis() + 10 * 1000, new Runnable() {
/**
@@ -1700,7 +1604,7 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
knownReplies.remove(reply.getId());
}
sone.removeReply(reply);
- saveSone(sone);
+ touchConfiguration();
}
/**
@@ -1715,44 +1619,177 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
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.
*/
- public void start() {
+ @Override
+ public void serviceStart() {
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.
*/
- public void stop() {
+ @Override
+ public void serviceStop() {
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();
- 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.getBooleanValue(sonePrefix + "/Options/EnableSoneInsertNotifications").setValue(sone.getOptions().getBooleanOption("EnableSoneInsertNotifications").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.
*/
- public void saveConfiguration() {
+ private void saveConfiguration() {
synchronized (configuration) {
if (storingConfiguration) {
logger.log(Level.FINE, "Already storing configurationâ¦");
@@ -1825,10 +1862,6 @@ public class Core implements IdentityListener, UpdateListener, SoneProvider, Pos
}
}
- //
- // PRIVATE METHODS
- //
-
/**
* Loads the configuration.
*/