m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2020-01-06 12:02:46 +0100
committerMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2020-01-06 12:02:46 +0100
commit88cc1f5da8ded831b15f4970e8877494d449a471 (patch)
treefcf3141fd7acbf19b87ea4eb215e39220137aa09 /src
parent89a5d7b00f71a5be805ecc7e7907e5b0c88c5f03 (diff)
Prune hierarchy of stale zones on read
Diffstat (limited to 'src')
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java44
-rw-r--r--src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java29
2 files changed, 69 insertions, 4 deletions
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java
index 1b1824f..6c0f380 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java
@@ -1,6 +1,8 @@
package pl.edu.mimuw.cloudatlas.agent.modules;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map.Entry;
import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage;
@@ -19,6 +21,7 @@ import pl.edu.mimuw.cloudatlas.model.Type;
import pl.edu.mimuw.cloudatlas.model.TypePrimitive;
import pl.edu.mimuw.cloudatlas.model.Value;
import pl.edu.mimuw.cloudatlas.model.ValueBoolean;
+import pl.edu.mimuw.cloudatlas.model.ValueDuration;
import pl.edu.mimuw.cloudatlas.model.ValueQuery;
import pl.edu.mimuw.cloudatlas.model.ValueString;
import pl.edu.mimuw.cloudatlas.model.ValueTime;
@@ -36,12 +39,16 @@ public class Stanik extends Module {
private HashMap<Attribute, Entry<ValueQuery, ValueTime>> queries;
private long freshnessPeriod;
- public Stanik() {
+ public Stanik(long freshnessPeriod) {
super(ModuleType.STATE);
hierarchy = new ZMI();
queries = new HashMap<Attribute, Entry<ValueQuery, ValueTime>>();
hierarchy.getAttributes().add("timestamp", new ValueTime(0l));
- freshnessPeriod = 60 * 1000;
+ this.freshnessPeriod = freshnessPeriod;
+ }
+
+ public Stanik() {
+ this(60 * 1000);
}
public void handleTyped(StanikMessage message) throws InterruptedException, InvalidMessageType {
@@ -67,6 +74,7 @@ public class Stanik extends Module {
}
public void handleGetState(GetStateMessage message) throws InterruptedException {
+ pruneHierarchy();
StateMessage response = new StateMessage(
"",
message.getRequestingModule(),
@@ -78,6 +86,38 @@ public class Stanik extends Module {
sendMessage(response);
}
+ private void pruneHierarchy() {
+ ValueTime now = ValueUtils.currentTime();
+ pruneZMI(hierarchy, now);
+ }
+
+ private boolean pruneZMI(ZMI zmi, ValueTime time) {
+ Value timestamp = zmi.getAttributes().get("timestamp");
+
+ List<ZMI> sonsToRemove = new LinkedList();
+ if (ValueUtils.valueLower(timestamp, time.subtract(new ValueDuration(freshnessPeriod)))) {
+ if (zmi.getFather() != null) {
+ return true;
+ }
+ } else {
+ for (ZMI son : zmi.getSons()) {
+ if (pruneZMI(son, time)) {
+ sonsToRemove.add(son);
+ }
+ }
+ }
+
+ for (ZMI son : sonsToRemove) {
+ zmi.removeSon(son);
+ }
+
+ if (zmi.getSons().isEmpty()) {
+ return true;
+ }
+
+ return false;
+ }
+
public void handleRemoveZMI(RemoveZMIMessage message) {
try {
ZMI zmi = hierarchy.findDescendant(new PathName(message.getPathName()));
diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java
index 1ca8608..f3ea0b0 100644
--- a/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java
+++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java
@@ -35,10 +35,11 @@ public class StanikTest {
private Stanik stanik;
private MockExecutor executor;
private ValueTime testTime;
+ private static final long freshnessPeriod = 1000;
@Before
public void setupLocals() {
- stanik = new Stanik();
+ stanik = new Stanik(freshnessPeriod);
executor = new MockExecutor(stanik);
testTime = ValueUtils.currentTime();
}
@@ -157,7 +158,7 @@ public class StanikTest {
public void dontApplyWithStaleTimestamp() throws Exception {
AttributesMap attributes = new AttributesMap();
attributes.add("foo", new ValueInt(1337l));
- attributes.add("timestamp", (ValueTime) testTime.subtract(new ValueDuration(61 * 1000l)));
+ attributes.add("timestamp", (ValueTime) testTime.subtract(new ValueDuration(freshnessPeriod + 100)));
attributes.add("name", new ValueString("new"));
UpdateAttributesMessage message = new UpdateAttributesMessage("test_msg", 0, "/new", attributes);
stanik.handleTyped(message);
@@ -166,6 +167,30 @@ public class StanikTest {
}
@Test
+ public void zoneRemovedAfterFreshnessPeriod() throws Exception {
+ AttributesMap attributes = new AttributesMap();
+ attributes.add("foo", new ValueInt(1337l));
+ attributes.add("timestamp", testTime);
+ attributes.add("name", new ValueString("new"));
+ UpdateAttributesMessage message = new UpdateAttributesMessage("test_msg", 0, "/new", attributes);
+ stanik.handleTyped(message);
+ Thread.sleep(freshnessPeriod + 100);
+
+ AttributesMap attributes2 = new AttributesMap();
+ attributes2.add("timestamp", ValueUtils.currentTime());
+ UpdateAttributesMessage message2 = new UpdateAttributesMessage("test_msg", 0, "/", attributes2);
+ stanik.handleTyped(message2);
+
+ GetStateMessage getStateMessage = new GetStateMessage("", 0, ModuleType.TEST, 0);
+ stanik.handleTyped(getStateMessage);
+
+ StateMessage newReceivedMessage = (StateMessage) executor.messagesToPass.poll();
+ assertNotNull(newReceivedMessage);
+ assertFalse(newReceivedMessage.getZMI().descendantExists(new PathName("/new")));
+ assertFalse(stanik.getHierarchy().descendantExists(new PathName("/new")));
+ }
+
+ @Test
public void addQuery() throws Exception {
HashMap<Attribute, Entry<ValueQuery, ValueTime>> queries = new HashMap<Attribute, Entry<ValueQuery, ValueTime>>();
queries.put(new Attribute("&query"), new SimpleImmutableEntry(new ValueQuery("SELECT 1 AS one"), new ValueTime(42l)));