Skip to content

Commit a20f647

Browse files
committed
multiple results in list enabled
1 parent a5a3324 commit a20f647

File tree

4 files changed

+93
-42
lines changed

4 files changed

+93
-42
lines changed

src/main/kotlin/no/uio/microobject/ast/stmt/MonitorStmt.kt

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -76,32 +76,35 @@ class MonitorObject(private val name: LiteralExpr, private val declaredType: Typ
7676
}
7777

7878
fun getWindowResults(interpreter: Interpreter): LiteralExpr {
79-
val rdfTable = interpreter.streamManager.getQueryResults(name)
79+
val rdfTables = interpreter.streamManager.getQueryResults(name)
80+
8081
var list = LiteralExpr("null")
8182

82-
if (rdfTable != null) {
83+
if (rdfTables != null) {
84+
for (rdfTable in rdfTables) {
8385

84-
val resIt = rdfTable.rows().iterator()
85-
val firstVar = rdfTable.varNames.get(0)
86-
while (resIt.hasNext()) {
87-
val rdfTuple = resIt.next()
88-
try {
89-
// only consider first result for now
90-
var literal = iriToLiteral(rdfTuple.get(firstVar).toString(), interpreter)
91-
if (literal.tag != declaredType)
92-
throw Exception("Monitor parameter has incorrect type (expected ${declaredType}, got ${literal.tag})")
86+
val resIt = rdfTable.rows().iterator()
87+
val firstVar = rdfTable.varNames.get(0)
88+
89+
while (resIt.hasNext()) {
90+
val rdfTuple = resIt.next()
91+
try {
92+
// only consider first result for now
93+
var literal = iriToLiteral(rdfTuple.get(firstVar).toString(), interpreter)
94+
if (literal.tag != declaredType)
95+
throw Exception("Monitor parameter has incorrect type (expected ${declaredType}, got ${literal.tag})")
9396

94-
val name = Names.getObjName("List")
95-
val newMemory: Memory = mutableMapOf()
96-
newMemory["content"] = literal
97-
newMemory["next"] = list
98-
interpreter.heap[name] = newMemory
99-
list = name
97+
val name = Names.getObjName("List")
98+
val newMemory: Memory = mutableMapOf()
99+
newMemory["content"] = literal
100+
newMemory["next"] = list
101+
interpreter.heap[name] = newMemory
102+
list = name
100103

101-
} catch (e: Exception) {
102-
throw Exception("Error while processing query result: ${e.message}")
104+
} catch (e: Exception) {
105+
throw Exception("Error while processing query result: ${e.message}")
106+
}
103107
}
104-
105108
}
106109
}
107110
return list

src/main/kotlin/no/uio/microobject/data/StreamManager.kt

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ import org.streamreasoning.rsp4j.api.sds.SDSConfiguration
3838
import org.apache.jena.rdf.model.*;
3939
import org.apache.jena.atlas.lib.tuple.Tuple
4040

41+
// Per-monitor state
42+
data class WindowBuf(var tick: Long? = null, val current: MutableList<Table> = mutableListOf())
43+
4144
// Class managing streams
4245
class StreamManager(private val settings: Settings, val staticTable: StaticTable, private val interpreter: Interpreter?) {
4346

@@ -50,12 +53,14 @@ class StreamManager(private val settings: Settings, val staticTable: StaticTable
5053
private var streams: MutableMap<String, MutableMap<LiteralExpr, StreamObject>> = mutableMapOf()
5154
private var monitors: MutableMap<LiteralExpr, MonitorObject> = mutableMapOf()
5255

53-
private var queryResults: MutableMap<LiteralExpr, Table?> = ConcurrentHashMap()
56+
private val windowBufs = ConcurrentHashMap<LiteralExpr, WindowBuf>()
57+
private val queryResults = ConcurrentHashMap<LiteralExpr, List<Table>>() // read-only snapshots
5458

5559
var clockVar : String? = null
5660
var clockTimestampSec : String? = null
5761
var lastTimestamp: Long = 0
58-
62+
var lastWindowTs: Long? = null
63+
5964
var nStaticGraphsPushed = 0
6065

6166
init {
@@ -89,12 +94,12 @@ class StreamManager(private val settings: Settings, val staticTable: StaticTable
8994
sdsConfig = SDSConfiguration(defaultPath)
9095
}
9196

92-
engine = CSPARQLEngine(0, ec)
97+
engine = CSPARQLEngine(ts, ec)
9398
engineInitialized = true
9499
}
95100
}
96101

97-
public fun getQueryResults(name: LiteralExpr): Table? {
102+
public fun getQueryResults(name: LiteralExpr): List<Table>? {
98103
return queryResults[name]
99104
}
100105

@@ -130,13 +135,27 @@ class StreamManager(private val settings: Settings, val staticTable: StaticTable
130135
val stream = streams[className]!![obj]!!
131136
val expressions = interpreter!!.staticInfo.streamersTable[className]!![methodName]!!
132137

133-
val subjIri = "${settings.runPrefix}${obj.literal}"
134138
val timestamp = getTimestamp()
135139

136140
for (expr in expressions) {
137141
val res = interpreter.eval(expr, stackEntry)
138142

139-
val predIri = "${settings.progPrefix}${className}_${expr.toString().removePrefix("this.").replace('.', '_')}"
143+
val exprParts = expr.toString().split('.')
144+
var subjIri: String = "${settings.runPrefix}${obj.literal}"
145+
var predIri = "${settings.progPrefix}${className}_${expr.toString().removePrefix("this.").replace('.', '_')}"
146+
if (exprParts.size < 2) {
147+
throw Exception("Streamer expression must be of the form this.field or this.obj.field")
148+
}
149+
if (exprParts.size > 2) {
150+
// find the one before last part
151+
var currentObj: LiteralExpr = obj
152+
for (i in 1 until exprParts.size - 1) {
153+
val fieldName = exprParts[i]
154+
currentObj = interpreter.heap[currentObj]!![fieldName]!!
155+
}
156+
subjIri = "${settings.runPrefix}${currentObj.literal}"
157+
predIri = "${settings.progPrefix}${(currentObj.tag as BaseType).name}_${exprParts.last()}"
158+
}
140159

141160
val m = ModelFactory.createDefaultModel()
142161
val stmt = m.createStatement(m.createResource(subjIri), m.createProperty(predIri), literalToIri(m, res, settings))
@@ -162,14 +181,25 @@ class StreamManager(private val settings: Settings, val staticTable: StaticTable
162181
public fun registerQuery(name: LiteralExpr, queryExpr : Expression, params: List<Expression>, stackMemory: Memory, heap: GlobalMemory, obj: LiteralExpr, SPARQL : Boolean = true, declaredType: Type): JenaContinuousQueryExecution {
163182
initEngineIfNeeded()
164183
val queryStr = prepareQuery(name, queryExpr, params, stackMemory, heap, obj, SPARQL)
184+
if (settings.verbose) println("Registering query:\n$queryStr")
165185

166186
val cqe = engine!!.register(queryStr, sdsConfig) as JenaContinuousQueryExecution
167187
monitors[name] = MonitorObject(name, declaredType)
168188

189+
windowBufs.computeIfAbsent(name) { WindowBuf() }
190+
169191
val outputStream = cqe.outstream()
170-
outputStream?.addConsumer { arg, ts ->
171-
val results: Table = arg as Table
172-
queryResults[name] = results
192+
outputStream?.addConsumer { arg, ts ->
193+
val table = arg as Table
194+
val b = windowBufs.getOrPut(name) { WindowBuf() }
195+
196+
if (b.tick != ts) {
197+
b.tick = ts
198+
b.current.clear()
199+
}
200+
b.current += table
201+
202+
queryResults[name] = b.current.toList()
173203
}
174204

175205
return cqe
@@ -181,7 +211,7 @@ class StreamManager(private val settings: Settings, val staticTable: StaticTable
181211
var prefixes = ""
182212
for ((key, value) in settings.prefixMap()) prefixes += "PREFIX $key: <$value>\n"
183213

184-
val queryHeader = "REGISTER RSTREAM <${settings.runPrefix}${name.literal}> AS "
214+
val queryHeader = "REGISTER RSTREAM <${settings.runPrefix}${name.literal}/out> AS "
185215

186216
val queryBody = interpreter!!.prepareQuery(queryExpr, params, stackMemory, heap, obj, SPARQL)
187217
.removePrefix("\"").removeSuffix("\"")

src/main/resources/default-csparql2.properties

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
rsp_engine.time=EventTime
2-
# rsp_engine.base_uri=http://streamreasoning.org/csparql/
32
rsp_engine.stream.item.class=org.streamreasoning.rsp4j.csparql2.stream.GraphStreamSchema
43

54
rsp_engine.response_format=JSON-LD
65

7-
rsp_engine.on_window_close=true
6+
rsp_engine.on_window_close=false
87
rsp_engine.non_empty_content=true
98
rsp_engine.periodic=false
109
rsp_engine.on_content_change=false
1110
rsp_engine.tick=TIME_DRIVEN
1211

1312
rsp_engine.report_grain=SINGLE
1413
rsp_engine.sds.mantainance=NAIVE
15-
rsp_engine.partialwindow=false
14+
rsp_engine.partialwindow=true
1615

1716
# jasper.entailment=RDFS
1817
# rsp_engine.tbox_location=artist.tbox.owl

src/test/resources/csparql/04_no_aggregation.smol

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
streamer class C(Int x, Monitor<Int> m)
1+
// reada src/test/resources/csparql/04_no_aggregation.smol
2+
3+
class Observation(Int x, Int ts) end
4+
5+
streamer class C(Int x, Observation obs, Monitor<Int> m)
26

37
Unit register()
48
Monitor<Int> m = monitor("
59
SELECT ?x
6-
FROM STREAM %1 [RANGE 5s STEP 2s]
7-
WHERE { ?s prog:C_x ?x }
10+
FROM NAMED WINDOW <win> ON %1 [RANGE PT5.001s STEP PT2s]
11+
WHERE {
12+
WINDOW ?w { ?s prog:Observation_x ?x }
13+
}
814
", this);
915
this.m = m;
1016
end
1117

12-
Unit doStream() emits(this.x)
18+
Unit doStream(Int ts) emits(this.obs, this.obs.x, this.obs.ts)
1319
this.x = this.x + 1;
20+
this.obs = new Observation(this.x, ts);
1421
end
1522

1623
String windowToString()
@@ -25,16 +32,27 @@ streamer class C(Int x, Monitor<Int> m)
2532
end
2633

2734
main
28-
C o = new C(0, null);
29-
o.register();
30-
35+
// configure simulation
3136
clock Int i = 100;
3237
Int endAt = 200;
3338

39+
// initialize stream
40+
C o = new C(0, null, null);
41+
42+
// initialize monitor
43+
o.register();
44+
45+
// run simulation
3446
while i < endAt do
35-
o.doStream();
47+
48+
// put triples in the stream
49+
o.doStream(i);
50+
51+
// read window contents
3652
String res = o.windowToString();
3753
print(">>" ++ intToString(i) ++ ": " ++ res);
54+
55+
// advance clock (timestamp)
3856
i = i + 1;
3957
end
4058
end
@@ -52,4 +70,5 @@ end
5270
// ..
5371

5472
// Notes:
55-
// - Multiple elements in the window because there is no aggregation function
73+
// - Step 2 seconds = new window every 2 seconds
74+
// - Range 5.001s: Windows have {2, 4, 5, 5, 5, ...} elements

0 commit comments

Comments
 (0)