Skip to content

Commit

Permalink
0.7.0
Browse files Browse the repository at this point in the history
- Eliminate intermediate nodes named for the nav id.
- Fix set and getHistory actions when node tree doesn't exist.
- Add table metadata to history tables.
- Fix an infinite loop when clearing the node tree.
  • Loading branch information
a-hansen authored May 4, 2021
1 parent 1cdd387 commit 00a79f7
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 131 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ apply plugin: 'java-library'
mainClassName = 'org.dsa.iot.haystack.Main'
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '0.6.0'
version = '0.7.0'

repositories {
mavenLocal()
Expand Down
2 changes: 1 addition & 1 deletion dslink.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dslink-java-haystack",
"version": "0.6.0",
"version": "0.7.0",
"description": "An implementation dslink of a haystack protocol consumer",
"license": "Apache",
"author": {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/dsa/iot/haystack/Haystack.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public void editConnection(String url,
}

Action a = ServerActions.getEditAction(node);
node.getChild("editServer").setAction(a);
node.getChild("editServer", false).setAction(a);

}

Expand Down
63 changes: 52 additions & 11 deletions src/main/java/org/dsa/iot/haystack/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@
import org.dsa.iot.dslink.DSLinkFactory;
import org.dsa.iot.dslink.DSLinkHandler;
import org.dsa.iot.dslink.node.Node;
import org.dsa.iot.dslink.node.NodeBuilder;
import org.dsa.iot.dslink.node.NodeManager;
import org.dsa.iot.dslink.util.StringUtils;
import org.dsa.iot.haystack.actions.Actions;
import org.dsa.iot.haystack.actions.GetHistory;
import org.dsa.iot.haystack.actions.InvokeActions;
import org.dsa.iot.haystack.helpers.StateHandler;
import org.projecthaystack.HDict;
import org.projecthaystack.HGrid;
import org.projecthaystack.HRef;
import org.projecthaystack.HRow;
import org.projecthaystack.HStr;
import org.projecthaystack.HTimeZone;
import org.projecthaystack.HVal;
import org.projecthaystack.client.HClient;
import org.projecthaystack.io.HZincReader;
Expand Down Expand Up @@ -84,10 +85,10 @@ public Node onSubscriptionFail(String path) {
while (i < split.length) {
Node next = n.getChild(split[i], false);
int tries = 0;
while (next == null && tries < 6) {
while (next == null && tries < 10) {
tries++;
try {
subFailLock.wait(200);
subFailLock.wait(250);
} catch (InterruptedException ignore) {
}
next = n.getChild(split[i], false);
Expand Down Expand Up @@ -116,12 +117,56 @@ public Node onInvocationFail(final String path) {

final NodeManager manager = link.getNodeManager();
final Node superRoot = manager.getSuperRoot();
final Haystack haystack = superRoot.getChild(split[0]).getMetaData();
final Haystack haystack = superRoot.getChild(split[0], true).getMetaData();
final String actName = StringUtils.decodeName(split[split.length - 1]);

final CountDownLatch latch = new CountDownLatch(1);
final Container container = new Container();
if ("pointWrite".equals(actName)) {
if ("getHistory".equals(actName)) {
haystack.getConnHelper().getClient(new StateHandler<HClient>() {
@Override
public void handle(HClient event) {
final HRef id;
{
String sID = split[split.length - 3];
sID = StringUtils.decodeName(sID);
id = HRef.make(sID);
}

HDict dict = event.readById(id);
HVal tz = dict.get("tz", false);
HTimeZone htz = null;
if (tz != null) {
htz = HTimeZone.make(tz.toString(), false);
}

String[] pSplit = Arrays.copyOf(split, split.length - 1);
String parent = StringUtils.join(pSplit, "/");
Node node = manager.getNode(parent, true).getNode();
container.node = new GetHistory(node, haystack, HRef.make(id.toString()), htz)
.getActionNode();
latch.countDown();
}
});
} else if ("set".equals(actName)) {
haystack.getConnHelper().getClient(new StateHandler<HClient>() {
@Override
public void handle(HClient event) {
HDict dict = event.readById(id);
HVal hKind = dict.get("kind", false);
String kind = null;
if (hKind != null) {
kind = hKind.toString();
}

String[] pSplit = Arrays.copyOf(split, split.length - 1);
String parent = StringUtils.join(pSplit, "/");
Node node = manager.getNode(parent, true).getNode();
container.node = Actions.getSetAction(haystack, node, id, kind);
latch.countDown();
}
});
} else if ("pointWrite".equals(actName)) {
haystack.getConnHelper().getClient(new StateHandler<HClient>() {
@Override
public void handle(HClient event) {
Expand All @@ -135,11 +180,7 @@ public void handle(HClient event) {
String[] pSplit = Arrays.copyOf(split, split.length - 1);
String parent = StringUtils.join(pSplit, "/");
Node node = manager.getNode(parent, true).getNode();
NodeBuilder b = Utils.getBuilder(node, "pointWrite");
b.setDisplayName("Point Write");
b.setSerializable(false);
b.setAction(Actions.getPointWriteAction(haystack, id, kind));
container.node = b.build();
container.node = Actions.getPointWriteAction(haystack, node, id, kind);
latch.countDown();
}
});
Expand Down Expand Up @@ -170,7 +211,7 @@ public void handle(HClient event) {

String name = split[split.length - 1];
name = StringUtils.encodeName(name);
container.node = node.getChild(name);
container.node = node.getChild(name, false);
break;
}
if (doThrow) {
Expand Down
6 changes: 1 addition & 5 deletions src/main/java/org/dsa/iot/haystack/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,7 @@ public static void initCommon(Haystack haystack, Node node) {
subNode.setSerializable(false);
subNode.build();

NodeBuilder writeNode = getBuilder(node, "pointWrite");
writeNode.setDisplayName("Point Write");
writeNode.setAction(Actions.getPointWriteAction(haystack));
writeNode.setSerializable(false);
writeNode.build();
Actions.getPointWriteAction(haystack, node);

NodeBuilder invokeNode = getBuilder(node, "invoke");
invokeNode.setDisplayName("Invoke");
Expand Down
87 changes: 21 additions & 66 deletions src/main/java/org/dsa/iot/haystack/actions/Actions.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.Locale;
import java.util.Map;
import org.dsa.iot.dslink.methods.StreamState;
import org.dsa.iot.dslink.node.Node;
import org.dsa.iot.dslink.node.NodeBuilder;
import org.dsa.iot.dslink.node.Permission;
import org.dsa.iot.dslink.node.actions.Action;
import org.dsa.iot.dslink.node.actions.ActionResult;
Expand Down Expand Up @@ -79,13 +81,14 @@ public void handle(Void event) {
return a;
}

public static Action getPointWriteAction(Haystack haystack) {
return getPointWriteAction(haystack, null, null);
public static Node getPointWriteAction(Haystack haystack, Node parent) {
return getPointWriteAction(haystack, parent, null, null);
}

public static Action getPointWriteAction(final Haystack haystack,
final HRef treeId,
final String kind) {
public static Node getPointWriteAction(final Haystack haystack,
final Node parent,
final HRef treeId,
final String kind) {
Action a = new Action(Permission.READ, new Handler<ActionResult>() {
@Override
public void handle(final ActionResult event) {
Expand Down Expand Up @@ -236,12 +239,17 @@ public void handle(HClient client) {
p.setDescription("Duration unit.");
a.addParameter(p);
}
return a;
NodeBuilder writeNode = Utils.getBuilder(parent, "pointWrite");
writeNode.setDisplayName("Point Write");
writeNode.setSerializable(false);
writeNode.setAction(a);
return writeNode.build();
}

public static Action getSetAction(final Haystack haystack,
final HRef treeId,
final String kind) {
public static Node getSetAction(final Haystack haystack,
final Node parent,
final HRef treeId,
final String kind) {
final String type = kind.toLowerCase(Locale.ROOT);
final ValueType valueType;
switch (type) {
Expand Down Expand Up @@ -293,7 +301,10 @@ public void handle(HClient client) {
});
Parameter p = new Parameter("Value", valueType);
a.addParameter(p);
return a;
return parent.createChild("set", false)
.setAction(a)
.setDisplayName("Set")
.build();
}

public static Action getReadAction(final Haystack haystack) {
Expand Down Expand Up @@ -392,62 +403,6 @@ public void handle(HGrid grid) {
return a;
}

/* todo Save for awhile
public static Action getHistoryAction(final Haystack haystack,
final HRef treeId,
final TimeZone tz) {
Action a = new Action(Permission.READ, new Handler<ActionResult>() {
@Override
public void handle(final ActionResult event) {
if (!haystack.isEnabled()) {
throw new IllegalStateException("Disabled");
}
Value vRange = event.getParameter("Timerange", ValueType.STRING);
String range = vRange.getString();
String[] split = range.split("/");
Calendar cal = TimeUtils.decode(split[0], null);
if (tz != null) {
cal.setTimeZone(tz);
}
StringBuilder buf = new StringBuilder();
TimeUtils.encode(cal, true, buf);
buf.append(',');
TimeUtils.decode(split[1], cal);
if (tz != null) {
cal.setTimeZone(tz);
}
TimeUtils.encode(cal, true, buf);
HGridBuilder builder = new HGridBuilder();
builder.addCol("id");
builder.addCol("range");
builder.addRow(new HVal[]{
HRef.make(treeId.toString()),
HStr.make(buf.toString())
});
haystack.call("hisRead", builder.toGrid(), new Handler<HGrid>() {
@Override
public void handle(HGrid grid) {
if (grid != null) {
buildTable(grid, event, true);
}
}
});
}
});
//parameters
Parameter param = new Parameter("Timerange", ValueType.STRING);
param.setEditorType(EditorType.DATE_RANGE);
a.addParameter(param);
//results
a.addResult(new Parameter("timestamp", ValueType.TIME));
a.addResult(new Parameter("value", ValueType.DYNAMIC));
a.setResultType(ResultType.TABLE);
return a;
}
*/

public static void buildTable(HGrid in, ActionResult out, boolean historyColNames) {
Table t = out.getTable();

Expand Down
36 changes: 31 additions & 5 deletions src/main/java/org/dsa/iot/haystack/actions/GetHistory.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.dsa.iot.dslink.methods.StreamState;
import org.dsa.iot.dslink.node.Node;
import org.dsa.iot.dslink.node.NodeBuilder;
Expand All @@ -24,6 +25,7 @@
import org.dsa.iot.dslink.util.TimeUtils;
import org.dsa.iot.dslink.util.handler.CompleteHandler;
import org.dsa.iot.dslink.util.handler.Handler;
import org.dsa.iot.dslink.util.json.JsonObject;
import org.dsa.iot.haystack.Haystack;
import org.dsa.iot.haystack.Utils;
import org.dsa.iot.historian.stats.interval.IntervalParser;
Expand All @@ -32,6 +34,7 @@
import org.dsa.iot.historian.utils.QueryData;
import org.projecthaystack.HCol;
import org.projecthaystack.HDateTime;
import org.projecthaystack.HDict;
import org.projecthaystack.HGrid;
import org.projecthaystack.HGridBuilder;
import org.projecthaystack.HRef;
Expand All @@ -55,6 +58,7 @@ public class GetHistory implements Handler<ActionResult> {
private static final Parameter TIMESTAMP = new Parameter("timestamp", ValueType.TIME);
private static final Parameter VALUE = new Parameter("value", ValueType.DYNAMIC);

private Node actionNode;
private final Haystack haystack;
private final HRef id;
private final HTimeZone tz;
Expand Down Expand Up @@ -93,6 +97,10 @@ public GetHistory(Node node,
initAction(node);
}

public Node getActionNode() {
return actionNode;
}

@Override
public void handle(final ActionResult event) {
long from;
Expand Down Expand Up @@ -137,7 +145,7 @@ protected void process(final ActionResult event,
final StringBuilder buffer = new StringBuilder();
final Calendar calendar = TimeUtils.reuseCalendar();
calendar.setTimeZone(tz.java);
query(from, to, new CompleteHandler<QueryData>() {
query(table, from, to, new CompleteHandler<QueryData>() {

private List<QueryData> updates = new LinkedList<>();

Expand Down Expand Up @@ -170,7 +178,7 @@ public void complete() {
});
}

protected void query(long from, long to, final CompleteHandler<QueryData> handler) {
protected void query(final Table table, long from, long to, final CompleteHandler<QueryData> handler) {
StringBuilder buf = new StringBuilder();
buf.append(HDateTime.make(from, tz));
buf.append(',');
Expand All @@ -186,7 +194,7 @@ protected void query(long from, long to, final CompleteHandler<QueryData> handle
haystack.call("hisRead", builder.toGrid(), new Handler<HGrid>() {
@Override
public void handle(HGrid grid) {
LoopProvider.getProvider().schedule(new QueryProcessor(grid, handler));
LoopProvider.getProvider().schedule(new QueryProcessor(table, grid, handler));
}
});
}
Expand Down Expand Up @@ -246,24 +254,42 @@ private void initAction(Node node) {
a.setResultType(ResultType.STREAM);

NodeBuilder b = node.createChild("getHistory", false);
b.setProfile("getHistory_");
b.setDisplayName("Get History");
b.setSerializable(false);
b.setAction(a);
b.build();
actionNode = b.build();
}

private static class QueryProcessor implements Runnable {

private final HGrid grid;
private final CompleteHandler<QueryData> handler;
private final Table table;

QueryProcessor(HGrid grid, CompleteHandler<QueryData> handler) {
QueryProcessor(Table table, HGrid grid, CompleteHandler<QueryData> handler) {
this.grid = grid;
this.handler = handler;
this.table = table;
}

public void run() {
try {
HDict meta = grid.meta();
if (meta != null && !meta.isEmpty()) {
Iterator<?> it = meta.iterator();
JsonObject metaObj = new JsonObject();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String name = (String) entry.getKey();
if (name != null) {
HVal val = (HVal) entry.getValue();
Value value = Utils.hvalToVal(val);
metaObj.put(name, value);
}
}
table.setTableMeta(metaObj);
}
HCol ts = grid.col("ts");
HCol val = grid.col("val");
Iterator it = grid.iterator();
Expand Down
Loading

0 comments on commit 00a79f7

Please sign in to comment.