diff --git a/tmc-plugin/src/fi/helsinki/cs/tmc/spyware/EventRateLimiter.java b/tmc-plugin/src/fi/helsinki/cs/tmc/spyware/EventRateLimiter.java
deleted file mode 100644
index d01230ef..00000000
--- a/tmc-plugin/src/fi/helsinki/cs/tmc/spyware/EventRateLimiter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package fi.helsinki.cs.tmc.spyware;
-
-import fi.helsinki.cs.tmc.utilities.LazyHashMap;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.Callable;
-
-/**
- * Buffers the latest version of an event and sends it at most with a certain interval.
- *
- *
- * An event rate limiter forwards events to another receiver.
- * When an event with a key {@code K} comes in,
- * a cooldown is activated. No other event with key {@code K} will be sent while
- * the cooldown is active. When the cooldown for {@code K} expires,
- * the most recent {@code K} received during the cooldown period is sent,
- * if any.
- *
- *
- * Separating the concern of rate limiting here allows event sources to
- * fire as many events as they want, as long as they are fine with some events
- * being discarded.
- */
-@Deprecated // Decided against using it for now. Might will use later, so won't delete yet (20120513).
-public class EventRateLimiter implements EventReceiver {
- public static final long DEFAULT_COOLDOWN = 30*1000;
-
- private class EventKeyRecord {
- private long cooldownLength = DEFAULT_COOLDOWN;
- private LoggableEvent newestUnsent = null;
- private Timer cooldownTimer = null;
-
- public synchronized void receive(LoggableEvent ev) {
- if (cooldownTimer == null) {
- assert newestUnsent == null;
- nextReceiver.receiveEvent(ev);
-
- cooldownTimer = new Timer("EventRateLimiter cooldown", true);
- cooldownTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- forwardFromTimer();
- }
- }, cooldownLength);
- } else {
- newestUnsent = ev;
- }
- }
-
- public synchronized void setCooldown(long cooldownLength) {
- this.cooldownLength = cooldownLength;
- }
-
- public synchronized void close() { //TODO: unit test
- if (cooldownTimer != null) {
- cooldownTimer.cancel();
- }
- if (newestUnsent != null) {
- nextReceiver.receiveEvent(newestUnsent);
- newestUnsent = null;
- }
- }
-
- private synchronized void forwardFromTimer() {
- if (newestUnsent != null) {
- nextReceiver.receiveEvent(newestUnsent);
- newestUnsent = null;
- }
-
- cooldownTimer = null;
- }
- }
-
- private final EventReceiver nextReceiver;
-
- private final LazyHashMap recordsByKey = new LazyHashMap(new Callable() {
- @Override
- public EventKeyRecord call() throws Exception {
- return new EventKeyRecord();
- }
- });
-
- public EventRateLimiter(EventReceiver nextReceiver) {
- this.nextReceiver = nextReceiver;
- }
-
- public synchronized void setCooldownForEventKey(String eventKey, long delayMillis) {
- recordsByKey.get(eventKey).setCooldown(delayMillis);
- }
-
- @Override
- public synchronized void receiveEvent(LoggableEvent event) {
- recordsByKey.get(event.getKey()).receive(event);
- }
-
- /**
- * Flush and close.
- */
- @Override
- public void close() {
- for (EventKeyRecord rec : recordsByKey.values()) {
- rec.close();
- }
- recordsByKey.clear();
- }
-}
diff --git a/tmc-plugin/src/fi/helsinki/cs/tmc/spyware/EventSendBuffer.java b/tmc-plugin/src/fi/helsinki/cs/tmc/spyware/EventSendBuffer.java
index 6ece39a4..81abe666 100644
--- a/tmc-plugin/src/fi/helsinki/cs/tmc/spyware/EventSendBuffer.java
+++ b/tmc-plugin/src/fi/helsinki/cs/tmc/spyware/EventSendBuffer.java
@@ -1,5 +1,7 @@
package fi.helsinki.cs.tmc.spyware;
+import static com.google.common.base.Preconditions.checkArgument;
+
import com.google.common.collect.Iterables;
import fi.helsinki.cs.tmc.data.Course;
import fi.helsinki.cs.tmc.model.CourseDb;
@@ -33,6 +35,7 @@ public class EventSendBuffer implements EventReceiver {
public static final int DEFAULT_MAX_EVENTS = 64 * 1024;
public static final int DEFAULT_AUTOSEND_THREHSOLD = DEFAULT_MAX_EVENTS / 2;
public static final int DEFAULT_AUTOSEND_COOLDOWN = 30*1000;
+ public static final int DEFAULT_MAX_EVENTS_PER_SEND = 500;
private Random random = new Random();
private SpywareSettings settings;
@@ -45,6 +48,7 @@ public class EventSendBuffer implements EventReceiver {
private int eventsToRemoveAfterSend = 0;
private int maxEvents = DEFAULT_MAX_EVENTS;
private int autosendThreshold = DEFAULT_AUTOSEND_THREHSOLD;
+ private int maxEventsPerSend = DEFAULT_MAX_EVENTS_PER_SEND; // Servers have POST size limits
private Cooldown autosendCooldown;
@@ -70,17 +74,17 @@ public EventSendBuffer(SpywareSettings settings, ServerAccess serverAccess, Cour
}
public void setSendingInterval(long interval) {
+ checkArgument(interval >= 0);
this.sendingTask.setInterval(interval);
}
public void setSavingInterval(long interval) {
+ checkArgument(interval >= 0);
this.savingTask.setInterval(interval);
}
public void setMaxEvents(int newMaxEvents) {
- if (newMaxEvents <= 0) {
- throw new IllegalArgumentException();
- }
+ checkArgument(newMaxEvents > 0);
synchronized (sendQueue) {
if (newMaxEvents < maxEvents) {
@@ -107,7 +111,17 @@ public void setAutosendThreshold(int autosendThreshold) {
}
public void setAutosendCooldown(long durationMillis) {
- this.autosendCooldown.setDurationMillis(durationMillis);
+ checkArgument(durationMillis > 0);
+ synchronized (sendQueue) {
+ this.autosendCooldown.setDurationMillis(durationMillis);
+ }
+ }
+
+ public void setMaxEventsPerSend(int maxEventsPerSend) {
+ checkArgument(maxEventsPerSend > 0);
+ synchronized (sendQueue) {
+ this.maxEventsPerSend = maxEventsPerSend;
+ }
}
public void sendNow() {
@@ -174,9 +188,6 @@ public void close() {
private SingletonTask sendingTask = new SingletonTask(new Runnable() {
- // Sending too many at once may go over the server's POST size limit.
- private static final int MAX_EVENTS_PER_SEND = 500;
-
@Override
public void run() {
boolean shouldSendMore;
@@ -198,7 +209,9 @@ public void run() {
log.log(Level.INFO, "Sending {0} events to {1}", new Object[] { eventsToSend.size(), url });
- doSend(eventsToSend, url);
+ if (!tryToSend(eventsToSend, url)) {
+ shouldSendMore = false;
+ }
} while (shouldSendMore);
}
@@ -207,7 +220,7 @@ private ArrayList copyEventsToSendFromQueue() {
ArrayList eventsToSend = new ArrayList(sendQueue.size());
Iterator i = sendQueue.iterator();
- while (i.hasNext() && eventsToSend.size() < MAX_EVENTS_PER_SEND) {
+ while (i.hasNext() && eventsToSend.size() < maxEventsPerSend) {
eventsToSend.add(i.next());
}
@@ -235,7 +248,7 @@ private String pickDestinationUrl() {
return url;
}
- private void doSend(final ArrayList eventsToSend, final String url) {
+ private boolean tryToSend(final ArrayList eventsToSend, final String url) {
CancellableCallable