LoggingActionQueue.java

1
package com.renomad.minum.logging;
2
3
import com.renomad.minum.queue.AbstractActionQueue;
4
import com.renomad.minum.queue.ActionQueue;
5
import com.renomad.minum.state.Constants;
6
import com.renomad.minum.utils.*;
7
8
import java.util.Map;
9
import java.util.concurrent.*;
10
11
import static com.renomad.minum.logging.Logger.showWhiteSpace;
12
import static com.renomad.minum.utils.TimeUtils.getTimestampIsoInstant;
13
14
/**
15
 * This class is very similar to {@link ActionQueue} but is
16
 * focused on Logging.
17
 * <p>
18
 *     It is necessary to create independent classes for logging to avoid circular dependencies
19
 * </p>
20
 */
21
final class LoggingActionQueue implements AbstractActionQueue {
22
    private final String name;
23
    private final ExecutorService executorService;
24
    private final LinkedBlockingQueue<RunnableWithDescription> queue;
25
    private Thread queueThread;
26
    /**
27
     * Set as volatile so that multiple threads may see the update
28
     * as soon as it occurs.
29
     */
30
    private volatile boolean stop = false;
31
    private boolean isStoppedStatus = false;
32
    private final Map<LoggingLevel, Boolean> enabledLogLevels;
33
34
    LoggingActionQueue(String name, ExecutorService executorService, Constants constants) {
35
        this.name = name;
36
        this.executorService = executorService;
37
        this.queue = new LinkedBlockingQueue<>();
38
        this.enabledLogLevels = Logger.convertToMap(constants.logLevels);
39
    }
40
41
    // Regarding the InfiniteLoopStatement - indeed, we expect that the while loop
42
    // below is an infinite loop unless there's an exception thrown, that is what it is.
43
    @Override
44
    @SuppressWarnings("InfiniteLoopStatement")
45
    public AbstractActionQueue initialize() {
46
        Runnable centralLoop = () -> {
47
            Thread.currentThread().setName(name);
48
            this.queueThread = Thread.currentThread();
49
            try {
50
                while (true) {
51
                    runAction(queue);
52
                }
53
            } catch (InterruptedException ex) {
54
                /*
55
                this is what we expect to happen.
56
                once this happens, we just continue on.
57
                this only gets called when we are trying to shut everything
58
                down cleanly
59
                 */
60
                Logger.logHelper(() -> String.format("%s LoggingActionQueue for %s is stopped.%n", TimeUtils.getTimestampIsoInstant(), name), LoggingLevel.DEBUG, enabledLogLevels, this);
61
                Thread.currentThread().interrupt();
62
            }
63
        };
64
        executorService.submit(centralLoop);
65 1 1. initialize : replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::initialize → KILLED
        return this;
66
    }
67
68
    /**
69
     * Runs the action that renders to a string for logging.
70
     * @return true if we successfully ran the action or false if there was an error
71
     */
72
    static boolean runAction(LinkedBlockingQueue<RunnableWithDescription> queue) throws InterruptedException {
73
        RunnableWithDescription action = queue.take();
74
        try {
75 1 1. runAction : removed call to com/renomad/minum/utils/RunnableWithDescription::run → TIMED_OUT
            action.run();
76 1 1. runAction : replaced boolean return with false for com/renomad/minum/logging/LoggingActionQueue::runAction → TIMED_OUT
            return true;
77
        } catch (Throwable e) {
78
            System.out.println(getTimestampIsoInstant() + " LOGGER_ERROR: " + showWhiteSpace(StacktraceUtils.stackTraceToString(e)));
79 1 1. runAction : replaced boolean return with true for com/renomad/minum/logging/LoggingActionQueue::runAction → KILLED
            return false;
80
        }
81
    }
82
83
    /**
84
     * Adds something to the queue to be processed.
85
     */
86
    @Override
87
    public void enqueue(String description, ThrowingRunnable action) {
88 1 1. enqueue : negated conditional → KILLED
        if (! stop) {
89
            queue.add(new RunnableWithDescription(action, description));
90
        }
91
    }
92
93
    /**
94
     * Stops the action queue
95
     * @param count how many loops to wait before we crash it closed
96
     * @param sleepTime how long to wait in milliseconds between loops
97
     */
98
    @Override
99
    public void stop(int count, int sleepTime) {
100
        Logger.logHelper(() -> String.format("%s Stopping queue %s%n", TimeUtils.getTimestampIsoInstant(), this), LoggingLevel.DEBUG, enabledLogLevels, this);
101
        stop = true;
102 2 1. stop : changed conditional boundary → TIMED_OUT
2. stop : negated conditional → TIMED_OUT
        for (int i = 0; i < count; i++) {
103 1 1. stop : negated conditional → TIMED_OUT
            if (queue.isEmpty()) return;
104
            Logger.logHelper(() -> String.format("%s Queue not yet empty, has %d elements. waiting...%n", TimeUtils.getTimestampIsoInstant(), queue.size()), LoggingLevel.DEBUG, enabledLogLevels, this);
105
            MyThread.sleep(sleepTime);
106
        }
107
        isStoppedStatus = true;
108
        Logger.logHelper(() -> String.format("%s Queue %s has %d elements left but we're done waiting.  Queue toString: %s",TimeUtils.getTimestampIsoInstant(), this, queue.size(), queue), LoggingLevel.DEBUG, enabledLogLevels, this);
109
    }
110
111
    /**
112
     * This will prevent any new actions being
113
     * queued (by setting the stop flag to true and thus
114
     * causing an exception to be thrown
115
     * when a call is made to [enqueue]) and will
116
     * block until the queue is empty.
117
     */
118
    @Override
119
    public void stop() {
120
        stop(5, 20);
121
    }
122
123
    public Thread getQueueThread() {
124 1 1. getQueueThread : replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueueThread → KILLED
        return queueThread;
125
    }
126
127
    @Override
128
    public LinkedBlockingQueue<RunnableWithDescription> getQueue() {
129 1 1. getQueue : replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueue → KILLED
        return queue;
130
    }
131
132
    @Override
133
    public String toString() {
134 1 1. toString : replaced return value with "" for com/renomad/minum/logging/LoggingActionQueue::toString → KILLED
        return this.name;
135
    }
136
137
    @Override
138
    public boolean isStopped() {
139 2 1. isStopped : replaced boolean return with false for com/renomad/minum/logging/LoggingActionQueue::isStopped → TIMED_OUT
2. isStopped : replaced boolean return with true for com/renomad/minum/logging/LoggingActionQueue::isStopped → TIMED_OUT
        return isStoppedStatus;
140
    }
141
}

Mutations

65

1.1
Location : initialize
Killed by : com.renomad.minum.web.PathDetailsTests
replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::initialize → KILLED

75

1.1
Location : runAction
Killed by : none
removed call to com/renomad/minum/utils/RunnableWithDescription::run → TIMED_OUT

76

1.1
Location : runAction
Killed by : none
replaced boolean return with false for com/renomad/minum/logging/LoggingActionQueue::runAction → TIMED_OUT

79

1.1
Location : runAction
Killed by : com.renomad.minum.logging.LoggingActionQueueTests
replaced boolean return with true for com/renomad/minum/logging/LoggingActionQueue::runAction → KILLED

88

1.1
Location : enqueue
Killed by : com.renomad.minum.logging.LoggingActionQueueTests
negated conditional → KILLED

102

1.1
Location : stop
Killed by : none
changed conditional boundary → TIMED_OUT

2.2
Location : stop
Killed by : none
negated conditional → TIMED_OUT

103

1.1
Location : stop
Killed by : none
negated conditional → TIMED_OUT

124

1.1
Location : getQueueThread
Killed by : com.renomad.minum.logging.LoggingActionQueueTests
replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueueThread → KILLED

129

1.1
Location : getQueue
Killed by : com.renomad.minum.logging.LoggingActionQueueTests
replaced return value with null for com/renomad/minum/logging/LoggingActionQueue::getQueue → KILLED

134

1.1
Location : toString
Killed by : com.renomad.minum.utils.MyThreadTests
replaced return value with "" for com/renomad/minum/logging/LoggingActionQueue::toString → KILLED

139

1.1
Location : isStopped
Killed by : none
replaced boolean return with false for com/renomad/minum/logging/LoggingActionQueue::isStopped → TIMED_OUT

2.2
Location : isStopped
Killed by : none
replaced boolean return with true for com/renomad/minum/logging/LoggingActionQueue::isStopped → TIMED_OUT

Active mutators

Tests examined


Report generated by PIT 1.17.0