/*
- * Sone - Core.java - Copyright © 2010–2019 David Roden
+ * Sone - Core.java - Copyright © 2010–2020 David Roden
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
import static java.lang.String.format;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
+import static net.pterodactylus.sone.data.AlbumKt.getAllImages;
import java.util.ArrayList;
import java.util.Collection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import com.codahale.metrics.*;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidImageFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
-import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
-import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent;
-import net.pterodactylus.sone.core.event.MarkPostKnownEvent;
-import net.pterodactylus.sone.core.event.MarkPostReplyKnownEvent;
-import net.pterodactylus.sone.core.event.MarkSoneKnownEvent;
-import net.pterodactylus.sone.core.event.NewPostFoundEvent;
-import net.pterodactylus.sone.core.event.NewPostReplyFoundEvent;
-import net.pterodactylus.sone.core.event.NewSoneFoundEvent;
-import net.pterodactylus.sone.core.event.PostRemovedEvent;
-import net.pterodactylus.sone.core.event.PostReplyRemovedEvent;
-import net.pterodactylus.sone.core.event.SoneLockedEvent;
-import net.pterodactylus.sone.core.event.SoneRemovedEvent;
-import net.pterodactylus.sone.core.event.SoneUnlockedEvent;
+import net.pterodactylus.sone.core.event.*;
import net.pterodactylus.sone.data.Album;
import net.pterodactylus.sone.data.Client;
import net.pterodactylus.sone.data.Image;
import net.pterodactylus.sone.data.Reply;
import net.pterodactylus.sone.data.Sone;
import net.pterodactylus.sone.data.Sone.SoneStatus;
+import net.pterodactylus.sone.data.SoneKt;
import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent;
import net.pterodactylus.sone.data.TemporaryImage;
import net.pterodactylus.sone.database.AlbumBuilder;
import net.pterodactylus.util.thread.NamedThreadFactory;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.FluentIterable;
+import com.google.common.base.Stopwatch;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
/** The time the configuration was last touched. */
private volatile long lastConfigurationUpdate;
- /**
- * Creates a new core.
- *
- * @param configuration
- * The configuration of the core
- * @param freenetInterface
- * The freenet interface
- * @param identityManager
- * The identity manager
- * @param webOfTrustUpdater
- * The WebOfTrust updater
- * @param eventBus
- * The event bus
- * @param database
- * The database
- */
+ private final MetricRegistry metricRegistry;
+ private final Histogram configurationSaveTimeHistogram;
+
+ private final SoneUriCreator soneUriCreator;
+
@Inject
- public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, SoneDownloader soneDownloader, ImageInserter imageInserter, UpdateChecker updateChecker, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, Database database) {
+ public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, SoneDownloader soneDownloader, ImageInserter imageInserter, UpdateChecker updateChecker, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, Database database, MetricRegistry metricRegistry, SoneUriCreator soneUriCreator) {
super("Sone Core");
this.configuration = configuration;
this.freenetInterface = freenetInterface;
this.webOfTrustUpdater = webOfTrustUpdater;
this.eventBus = eventBus;
this.database = database;
+ this.metricRegistry = metricRegistry;
+ this.soneUriCreator = soneUriCreator;
preferences = new Preferences(eventBus);
+ this.configurationSaveTimeHistogram = metricRegistry.histogram("configuration.save.duration", () -> new Histogram(new ExponentiallyDecayingReservoir(3000, 0)));
}
//
public void setDebug() {
debug.set(true);
+ eventBus.post(new DebugActivatedEvent());
}
/**
sone.setLatestEdition(fromNullable(tryParse(property)).or(0L));
sone.setClient(new Client("Sone", SonePlugin.getPluginVersion()));
sone.setKnown(true);
- SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, ownIdentity.getId());
+ SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, metricRegistry, soneUriCreator, ownIdentity.getId());
soneInserter.insertionDelayChanged(new InsertionDelayChangedEvent(preferences.getInsertionDelay()));
eventBus.register(soneInserter);
synchronized (soneInserters) {
loadSone(sone);
database.storeSone(sone);
sone.setStatus(SoneStatus.idle);
+ if (sone.getPosts().isEmpty() && sone.getReplies().isEmpty() && getAllImages(sone.getRootAlbum()).isEmpty()) {
+ // dirty hack
+ lockSone(sone);
+ eventBus.post(new SoneLockedOnStartup(sone));
+ }
soneInserter.start();
return sone;
}
}
/**
- * Sets the trust value of the given origin Sone for the target Sone.
- *
- * @param origin
- * The origin Sone
- * @param target
- * The target Sone
- * @param trustValue
- * The trust value (from {@code -100} to {@code 100})
- */
- public void setTrust(Sone origin, Sone target, int trustValue) {
- checkNotNull(origin, "origin must not be null");
- checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone");
- checkNotNull(target, "target must not be null");
- checkArgument((trustValue >= -100) && (trustValue <= 100), "trustValue must be within [-100, 100]");
- webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), trustValue, preferences.getTrustComment());
- }
-
- /**
- * Removes any trust assignment for the given target Sone.
- *
- * @param origin
- * The trust origin
- * @param target
- * The trust target
- */
- public void removeTrust(Sone origin, Sone target) {
- checkNotNull(origin, "origin must not be null");
- checkNotNull(target, "target must not be null");
- checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone");
- webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), null, null);
- }
-
- /**
- * Assigns the configured positive trust value for the given target.
- *
- * @param origin
- * The trust origin
- * @param target
- * The trust target
- */
- public void trustSone(Sone origin, Sone target) {
- setTrust(origin, target, preferences.getPositiveTrust());
- }
-
- /**
- * Assigns the configured negative trust value for the given target.
- *
- * @param origin
- * The trust origin
- * @param target
- * The trust target
- */
- public void distrustSone(Sone origin, Sone target) {
- setTrust(origin, target, preferences.getNegativeTrust());
- }
-
- /**
- * Removes the trust assignment for the given target.
- *
- * @param origin
- * The trust origin
- * @param target
- * The trust target
- */
- public void untrustSone(Sone origin, Sone target) {
- removeTrust(origin, target);
- }
-
- /**
* Updates the stored Sone with the given Sone.
*
* @param sone
synchronized (soneInserters) {
for (Entry<Sone, SoneInserter> soneInserter : soneInserters.entrySet()) {
soneInserter.getValue().stop();
- saveSone(soneInserter.getKey());
+ Sone latestSone = getLocalSone(soneInserter.getKey().getId());
+ saveSone(latestSone);
}
}
synchronized (soneRescuers) {
configuration.getStringValue(sonePrefix + "/Likes/Reply/" + replyLikeCounter + "/ID").setValue(null);
/* save albums. first, collect in a flat structure, top-level first. */
- List<Album> albums = FluentIterable.from(sone.getRootAlbum().getAlbums()).transformAndConcat(Album.FLATTENER).toList();
+ List<Album> albums = SoneKt.getAllAlbums(sone);
int albumCounter = 0;
for (Album album : albums) {
database.save();
/* now save it. */
+ Stopwatch stopwatch = Stopwatch.createStarted();
configuration.save();
+ configurationSaveTimeHistogram.update(stopwatch.elapsed(TimeUnit.MICROSECONDS));
} catch (ConfigurationException ce1) {
logger.log(Level.SEVERE, "Could not store configuration!", ce1);
*/
@Subscribe
public void ownIdentityAdded(OwnIdentityAddedEvent ownIdentityAddedEvent) {
- OwnIdentity ownIdentity = ownIdentityAddedEvent.ownIdentity();
+ OwnIdentity ownIdentity = ownIdentityAddedEvent.getOwnIdentity();
logger.log(Level.FINEST, String.format("Adding OwnIdentity: %s", ownIdentity));
if (ownIdentity.hasContext("Sone")) {
addLocalSone(ownIdentity);
*/
@Subscribe
public void ownIdentityRemoved(OwnIdentityRemovedEvent ownIdentityRemovedEvent) {
- OwnIdentity ownIdentity = ownIdentityRemovedEvent.ownIdentity();
+ OwnIdentity ownIdentity = ownIdentityRemovedEvent.getOwnIdentity();
logger.log(Level.FINEST, String.format("Removing OwnIdentity: %s", ownIdentity));
trustedIdentities.removeAll(ownIdentity);
}
*/
@Subscribe
public void identityAdded(IdentityAddedEvent identityAddedEvent) {
- Identity identity = identityAddedEvent.identity();
+ Identity identity = identityAddedEvent.getIdentity();
logger.log(Level.FINEST, String.format("Adding Identity: %s", identity));
- trustedIdentities.put(identityAddedEvent.ownIdentity(), identity);
+ trustedIdentities.put(identityAddedEvent.getOwnIdentity(), identity);
addRemoteSone(identity);
}
*/
@Subscribe
public void identityUpdated(IdentityUpdatedEvent identityUpdatedEvent) {
- Identity identity = identityUpdatedEvent.identity();
+ Identity identity = identityUpdatedEvent.getIdentity();
final Sone sone = getRemoteSone(identity.getId());
if (sone.isLocal()) {
return;
*/
@Subscribe
public void identityRemoved(IdentityRemovedEvent identityRemovedEvent) {
- OwnIdentity ownIdentity = identityRemovedEvent.ownIdentity();
- Identity identity = identityRemovedEvent.identity();
+ OwnIdentity ownIdentity = identityRemovedEvent.getOwnIdentity();
+ Identity identity = identityRemovedEvent.getIdentity();
trustedIdentities.remove(ownIdentity, identity);
for (Entry<OwnIdentity, Collection<Identity>> trustedIdentity : trustedIdentities.asMap().entrySet()) {
if (trustedIdentity.getKey().equals(ownIdentity)) {