m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/pl/edu/mimuw/cloudatlas/agent
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/pl/edu/mimuw/cloudatlas/agent')
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java83
1 files changed, 74 insertions, 9 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 a457a94..76ca0b6 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,5 +1,6 @@
package pl.edu.mimuw.cloudatlas.agent.modules;
+import java.util.Iterator;
import java.util.Map.Entry;
import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage;
@@ -10,16 +11,27 @@ import pl.edu.mimuw.cloudatlas.agent.messages.UpdateAttributesMessage;
import pl.edu.mimuw.cloudatlas.model.AttributesMap;
import pl.edu.mimuw.cloudatlas.model.Attribute;
import pl.edu.mimuw.cloudatlas.model.PathName;
+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.ValueString;
+import pl.edu.mimuw.cloudatlas.model.ValueTime;
import pl.edu.mimuw.cloudatlas.model.ZMI;
public class Stanik extends Module {
+ private class InvalidUpdateAttributesMessage extends Exception {
+ public InvalidUpdateAttributesMessage(String message) {
+ super(message);
+ }
+ }
+
private ZMI hierarchy;
public Stanik() {
super(ModuleType.STATE);
hierarchy = new ZMI();
+ hierarchy.getAttributes().add("timestamp", new ValueTime(0l));
}
public void handleTyped(StanikMessage message) throws InterruptedException, InvalidMessageType {
@@ -42,23 +54,75 @@ public class Stanik extends Module {
public void handleUpdateAttributes(UpdateAttributesMessage message) {
try {
+ validateUpdateAttributesMessage(message);
addMissingZones(new PathName(message.getPathName()));
ZMI zone = hierarchy.findDescendant(message.getPathName());
- for (Entry<Attribute, Value> entry : zone.getAttributes()) {
- Attribute attribute = entry.getKey();
- Value newValue = message.getAttributes().getOrNull(attribute);
- if (newValue == null) {
- zone.getAttributes().remove(attribute);
- }
- }
- for (Entry<Attribute, Value> entry : message.getAttributes()) {
- zone.getAttributes().addOrChange(entry.getKey(), entry.getValue());
+ AttributesMap attributes = zone.getAttributes();
+ if (valueLower(attributes.get("timestamp"), message.getAttributes().get("timestamp"))) {
+ transferAttributes(message.getAttributes(), attributes);
+ } else {
+ System.out.println("DEBUG: not applying update with older attributes");
}
+ } catch (InvalidUpdateAttributesMessage e) {
+ System.out.println("ERROR: invalid UpdateAttributesMessage " + e.getMessage());
} catch (ZMI.NoSuchZoneException e) {
System.out.println("ERROR: zone should exist after being added");
}
}
+ private boolean valueLower(Value a, Value b) {
+ return ((ValueBoolean) a.isLowerThan(b)).getValue();
+ }
+
+ private void validateUpdateAttributesMessage(UpdateAttributesMessage message) throws InvalidUpdateAttributesMessage {
+ validateZoneName(message);
+ validateHasTimeStamp(message);
+ }
+
+ private void validateZoneName(UpdateAttributesMessage message) throws InvalidUpdateAttributesMessage {
+ Value name = message.getAttributes().getOrNull("name");
+ if (message.getPathName().equals("/")) {
+ if (name != null && !name.isNull()) {
+ throw new InvalidUpdateAttributesMessage("The root zone should have a null name");
+ }
+ } else {
+ if (valueNonNullOfType(name, TypePrimitive.STRING)) {
+ ValueString nameString = (ValueString) name;
+ String expectedName = (new PathName(message.getPathName())).getSingletonName();
+ if (!nameString.getValue().equals(expectedName)) {
+ throw new InvalidUpdateAttributesMessage("The zone's name attribute should match its path name");
+ }
+ } else {
+ throw new InvalidUpdateAttributesMessage("Zone attributes should have a name attribute of type String");
+ }
+ }
+ }
+
+ private void validateHasTimeStamp(UpdateAttributesMessage message) throws InvalidUpdateAttributesMessage {
+ if (!valueNonNullOfType(message.getAttributes().getOrNull("timestamp"), TypePrimitive.TIME)) {
+ throw new InvalidUpdateAttributesMessage("Zone attriutes should have a timestamp attribute of type Time");
+ }
+ }
+
+ private boolean valueNonNullOfType(Value value, Type type) {
+ return value != null && !value.isNull() && value.getType().isCompatible(type);
+ }
+
+ private void transferAttributes(AttributesMap fromAttributes, AttributesMap toAttributes) {
+ Iterator<Entry<Attribute, Value>> iterator = toAttributes.iterator();
+ while (iterator.hasNext()) {
+ Entry<Attribute, Value> entry = iterator.next();
+ Attribute attribute = entry.getKey();
+ Value newValue = fromAttributes.getOrNull(attribute);
+ if (newValue == null) {
+ iterator.remove();
+ }
+ }
+ for (Entry<Attribute, Value> entry : fromAttributes) {
+ toAttributes.addOrChange(entry.getKey(), entry.getValue());
+ }
+ }
+
private void addMissingZones(PathName path) {
try {
if (!hierarchy.descendantExists(path)) {
@@ -66,6 +130,7 @@ public class Stanik extends Module {
ZMI parent = hierarchy.findDescendant(path.levelUp());
ZMI newSon = new ZMI(parent);
newSon.getAttributes().add("name", new ValueString(path.getSingletonName()));
+ newSon.getAttributes().add("timestamp", new ValueTime(0l));
parent.addSon(newSon);
}
} catch (ZMI.NoSuchZoneException e) {