• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Dynatrace / openkit-java / #421079372

pending completion
#421079372

push

github-actions

web-flow
Update build.gradle

4138 of 4351 relevant lines covered (95.1%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.71
/src/main/java/com/dynatrace/openkit/core/caching/BeaconCacheEvictor.java
1
/**
2
 * Copyright 2018-2021 Dynatrace LLC
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.dynatrace.openkit.core.caching;
18

19
import com.dynatrace.openkit.api.Logger;
20
import com.dynatrace.openkit.core.configuration.BeaconCacheConfiguration;
21
import com.dynatrace.openkit.providers.TimingProvider;
22

23
import java.util.Observable;
24
import java.util.Observer;
25
import java.util.concurrent.TimeUnit;
26

27
/**
28
 * Class responsible for handling an eviction thread, to ensure BeaconCache stays in configured boundaries.
29
 */
30
public class BeaconCacheEvictor {
31

32
    private static final String THREAD_NAME = BeaconCacheEvictor.class.getSimpleName();
1✔
33
    private static final long EVICTION_THREAD_JOIN_TIMEOUT = TimeUnit.SECONDS.toMillis(2);
1✔
34

35
    private final Logger logger;
36
    private final Thread evictionThread;
37

38
    /**
39
     * Public constructor, initializing the eviction thread with the default
40
     * {@link TimeEvictionStrategy} and {@link SpaceEvictionStrategy} strategies.
41
     *
42
     * @param logger         Logger to write some debug output
43
     * @param beaconCache    The Beacon cache to check if entries need to be evicted
44
     * @param configuration  Beacon cache configuration
45
     * @param timingProvider Timing provider required for time retrieval
46
     */
47
    public BeaconCacheEvictor(Logger logger, BeaconCache beaconCache, BeaconCacheConfiguration configuration, TimingProvider timingProvider) {
48
        this(logger, beaconCache, new TimeEvictionStrategy(logger, beaconCache, configuration, timingProvider), new SpaceEvictionStrategy(logger, beaconCache, configuration));
1✔
49
    }
1✔
50

51
    /**
52
     * Internal testing constructor.
53
     *
54
     * @param logger      Logger to write some debug output
55
     * @param beaconCache The Beacon cache to check if entries need to be evicted
56
     * @param strategies  Strategies passed to the actual Runnable.
57
     */
58
    BeaconCacheEvictor(Logger logger, BeaconCache beaconCache, BeaconCacheEvictionStrategy... strategies) {
1✔
59
        this.logger = logger;
1✔
60
        evictionThread = new Thread(new CacheEvictionRunnable(logger, beaconCache, strategies), THREAD_NAME);
1✔
61
        evictionThread.setDaemon(true);
1✔
62
    }
1✔
63

64
    /**
65
     * Starts the eviction thread.
66
     *
67
     * @return {@code true} if the eviction thread was started, {@code false} if the thread was already running.
68
     */
69
    public synchronized boolean start() {
70
        boolean result = false;
1✔
71

72
        if (!isAlive()) {
1✔
73
            evictionThread.start();
1✔
74
            result = true;
1✔
75
        } else {
76
            if (logger.isDebugEnabled()) {
1✔
77
                logger.debug(getClass().getSimpleName() + " start() - Not starting BeaconCacheEviction thread, since it's already running");
1✔
78
            }
79
        }
80

81
        return result;
1✔
82
    }
83

84
    /**
85
     * Stops the eviction thread and joins with {@link #EVICTION_THREAD_JOIN_TIMEOUT}.
86
     *
87
     * <p>
88
     * See also {@link #stop(long)}.
89
     * </p>
90
     */
91
    public boolean stop() {
92
        return stop(EVICTION_THREAD_JOIN_TIMEOUT);
1✔
93
    }
94

95
    /**
96
     * Stops the eviction thread via {@link Thread#interrupt()}, if it's alive and joins the eviction thread with given {@code timeout}.
97
     *
98
     * @param timeout The number of milliseconds to join the thread.
99
     *
100
     * @return {@code true} if stopping was successful, {@code false} if eviction thread is not running
101
     * or could not be stopped in time.
102
     */
103
    public synchronized boolean stop(long timeout) {
104
        boolean result = false;
1✔
105

106
        if (isAlive()) {
1✔
107
            if (logger.isDebugEnabled()) {
1✔
108
                logger.debug(getClass().getSimpleName() + " stop() - Stopping BeaconCacheEviction thread.");
1✔
109
            }
110
            evictionThread.interrupt();
1✔
111
            try {
112
                evictionThread.join(timeout);
1✔
113
                result = !isAlive();
1✔
114
            } catch (InterruptedException e) {
×
115
                logger.warning(getClass().getSimpleName() + " stop() - Stopping BeaconCacheEviction thread was interrupted.");
×
116
                Thread.currentThread().interrupt(); // re-interrupt the current thread
×
117
            }
1✔
118
        } else {
119
            if (logger.isDebugEnabled()) {
1✔
120
                logger.debug(getClass().getSimpleName() + " stop() - Not stopping BeaconCacheEviction thread, since it's not alive");
1✔
121
            }
122
        }
123

124
        return result;
1✔
125
    }
126

127
    public boolean isAlive() {
128
        return evictionThread.isAlive();
1✔
129
    }
130

131
    /**
132
     * Beacon cache eviction thread runnable.
133
     */
134
    private static final class CacheEvictionRunnable implements Runnable, Observer {
135

136
        private final Logger logger;
137
        private final Object lockObject = new Object();
1✔
138
        private boolean recordAdded = false;
1✔
139
        private final BeaconCache beaconCache;
140
        private final BeaconCacheEvictionStrategy[] strategies;
141

142
        CacheEvictionRunnable(Logger logger, BeaconCache beaconCache, BeaconCacheEvictionStrategy... strategies) {
1✔
143
            this.logger = logger;
1✔
144
            this.beaconCache = beaconCache;
1✔
145
            this.strategies = strategies;
1✔
146
        }
1✔
147

148
        @Override
149
        public void run() {
150
            if (logger.isDebugEnabled()) {
1✔
151
                logger.debug(getClass().getSimpleName() + " run() - BeaconCacheEviction thread started");
1✔
152
            }
153

154
            // first register ourselves
155
            beaconCache.addObserver(this);
1✔
156

157
            // run
158
            while (!Thread.currentThread().isInterrupted()) {
1✔
159
                synchronized (lockObject) {
1✔
160
                    try {
161
                        while (!recordAdded) {
1✔
162
                            lockObject.wait();
×
163
                        }
164
                    } catch (InterruptedException e) {
×
165
                        // re-interrupt the current thread
166
                        Thread.currentThread().interrupt();
×
167
                        break;
×
168
                    }
1✔
169

170
                    // reset the added flag
171
                    recordAdded = false;
1✔
172
                }
1✔
173

174
                // a new record has been added to the cache
175
                // run all eviction strategies, to perform cache cleanup
176
                for (BeaconCacheEvictionStrategy strategy : strategies) {
1✔
177
                    strategy.execute();
1✔
178
                }
179
            }
180

181
            if (logger.isDebugEnabled()) {
1✔
182
                logger.debug(getClass().getSimpleName() + " run() - thread is stopped");
1✔
183
            }
184
        }
1✔
185

186
        @Override
187
        public void update(Observable o, Object arg) {
188
            synchronized (lockObject) {
1✔
189
                recordAdded = true;
1✔
190
                lockObject.notifyAll();
1✔
191
            }
1✔
192
        }
1✔
193
    }
194
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc