Skip to content

Percentile Function Call throwing IndexOutOfBoundsException  #53

@fabes99

Description

@fabes99

Description:
Method getPercentileValue is not protected to the possibility of valueList to be empty due to event expiration. This provokes an IndexOutOfBoundsException. I am currently working on a use case where we need to compute percentiles over a sliding window and caught this situation. Currently, I am using a modified version of the extension in order cope with my requirements, but I am available to contribute it via PR.

Exception obtained:

19:13:35.621 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=1000, data=[1, 10.0], isExpired=false}]
19:13:35.625 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=1200, data=[1, 10.0], isExpired=false}]
19:13:35.626 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=1500, data=[1, 10.0], isExpired=false}]
WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
19:13:35.635 [main] ERROR io.siddhi.core.util.Scheduler - Error while sending timer events, Index -1 out of bounds for length 0
java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 0
at jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100) ~[?:?]
at jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106) ~[?:?]
at jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302) ~[?:?]
at java.util.Objects.checkIndex(Objects.java:359) ~[?:?]
at java.util.ArrayList.get(ArrayList.java:427) ~[?:?]
at io.siddhi.extension.execution.math.PercentileFunctionExtension.getPercentileValue(PercentileFunctionExtension.java:197) ~[classes/:?]
at io.siddhi.extension.execution.math.PercentileFunctionExtension.access$300(PercentileFunctionExtension.java:84) ~[classes/:?]
at io.siddhi.extension.execution.math.PercentileFunctionExtension$IntPercentileAttributeState.processRemove(PercentileFunctionExtension.java:325) ~[classes/:?]
at io.siddhi.extension.execution.math.PercentileFunctionExtension.processRemove(PercentileFunctionExtension.java:160) ~[classes/:?]
at io.siddhi.extension.execution.math.PercentileFunctionExtension.processRemove(PercentileFunctionExtension.java:50) ~[classes/:?]
at io.siddhi.core.query.selector.attribute.aggregator.AttributeAggregatorExecutor.processRemove(AttributeAggregatorExecutor.java:139) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.selector.attribute.aggregator.AttributeAggregatorExecutor.processAttributeArray(AttributeAggregatorExecutor.java:78) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.selector.attribute.aggregator.AttributeAggregatorExecutor.execute(AttributeAggregatorExecutor.java:61) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.selector.attribute.processor.AttributeProcessor.process(AttributeProcessor.java:41) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.selector.QuerySelector.processInBatchNoGroupBy(QuerySelector.java:284) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.selector.QuerySelector.process(QuerySelector.java:86) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.processor.stream.window.TimeWindowProcessor.process(TimeWindowProcessor.java:168) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.processor.stream.window.TimeWindowProcessor.process(TimeWindowProcessor.java:58) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.processor.stream.window.SlidingWindowProcessor.processEventChunk(SlidingWindowProcessor.java:74) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.processor.stream.AbstractStreamProcessor.process(AbstractStreamProcessor.java:133) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.query.input.stream.single.EntryValveProcessor.process(EntryValveProcessor.java:51) ~[siddhi-core-5.1.21.jar:?]
at io.siddhi.core.util.Scheduler.sendTimerEvents(Scheduler.java:196) [siddhi-core-5.1.21.jar:?]
at io.siddhi.core.util.Scheduler.access$300(Scheduler.java:49) [siddhi-core-5.1.21.jar:?]
at io.siddhi.core.util.Scheduler$1.onTimeChange(Scheduler.java:95) [siddhi-core-5.1.21.jar:?]
at io.siddhi.core.util.timestamp.TimestampGeneratorImpl.setCurrentTimestamp(TimestampGeneratorImpl.java:114) [siddhi-core-5.1.21.jar:?]
at io.siddhi.core.stream.input.InputHandler.send(InputHandler.java:76) [siddhi-core-5.1.21.jar:?]
at io.siddhi.extension.execution.math.Test.main(Test.java:43) [classes/:?]
19:13:35.666 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=7000, data=[1, 10.0], isExpired=false}]
19:13:35.667 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=8000, data=[1, 10.0], isExpired=false}]
19:13:35.667 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=9000, data=[1, 10.0], isExpired=false}]
19:13:35.668 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=11000, data=[1, 10.0], isExpired=false}]
19:13:35.668 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=12000, data=[1, 10.0], isExpired=false}]
19:13:35.669 [main] INFO  io.siddhi.core.util.EventPrinter - [Event{timestamp=12000, data=[1, 10.0], isExpired=false}]

Process finished with exit code 0

Affected Product Version:
5.0.4+

OS, DB, other environment details and versions:
Linux x64. OpenJDK 1.8.

Steps to reproduce:
The following code snippet can be used to reproduce the issue:

        SiddhiManager siddhiManager = new SiddhiManager();

        String executionPlan = ("@app:playback "
                + "define stream inputStream (sensorId int, temperature int); "
                + "partition with (sensorId of inputStream)\n"
                + "begin "
                + "@info(name = 'query1') from inputStream#window.time(5 sec) "
                + "select sensorId, math:percentile(temperature, 97.0) as percentile "
                + "insert all events into outputStream; " +
                "end;");
        SiddhiAppRuntime siddhiAppRuntime = siddhiManager
                .createSiddhiAppRuntime(executionPlan);

        siddhiAppRuntime.addCallback("outputStream", new StreamCallback() {
            @Override
            public void receive(Event[] events) {
                EventPrinter.print(events);
            }
        });

        InputHandler inputHandler = siddhiAppRuntime.getInputHandler("inputStream");
        siddhiAppRuntime.start();

        inputHandler.send(new Event(1000L,new Object[]{1, 10}));
        inputHandler.send(new Event(1200L,new Object[]{1, 10}));
        inputHandler.send(new Event(1500L,new Object[]{1, 10}));
        inputHandler.send(new Event(7000L,new Object[]{1, 10}));
        inputHandler.send(new Event(8000L,new Object[]{1, 10}));
        inputHandler.send(new Event(9000L,new Object[]{1, 10}));
        inputHandler.send(new Event(11000L,new Object[]{1, 10}));
        inputHandler.send(new Event(12000L,new Object[]{1, 10}));

        siddhiAppRuntime.shutdown();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions