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

oracle / opengrok / #3642

23 Oct 2023 02:33PM UTC coverage: 75.784% (+1.4%) from 74.413%
#3642

push

web-flow
Sonar code smell issue fixes (#4450)

Signed-off-by: Gino Augustine <ginoaugustine@gmail.com>

200 of 200 new or added lines in 39 files covered. (100.0%)

44390 of 58574 relevant lines covered (75.78%)

0.76 hits per line

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

65.08
/opengrok-indexer/src/main/java/org/opengrok/indexer/util/BoundedBlockingObjectPool.java
1
/*
2
 * The contents of this file are Copyright (c) 2012, Swaranga Sarma, DZone MVB
3
 * made available under free license,
4
 * http://javawithswaranga.blogspot.com/2011/10/generic-and-concurrent-object-pool.html
5
 * https://dzone.com/articles/generic-and-concurrent-object : "Feel free to use
6
 * it, change it, add more implementations. Happy coding!"
7
 * Portions Copyright (c) 2017-2018, Chris Fraire <cfraire@me.com>.
8
 * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
9
 */
10

11
package org.opengrok.indexer.util;
12

13
import java.util.concurrent.Callable;
14
import java.util.concurrent.ExecutorService;
15
import java.util.concurrent.Executors;
16
import java.util.concurrent.LinkedBlockingDeque;
17
import java.util.concurrent.TimeUnit;
18
import java.util.logging.Level;
19
import java.util.logging.Logger;
20

21
import org.opengrok.indexer.configuration.OpenGrokThreadFactory;
22
import org.opengrok.indexer.logger.LoggerFactory;
23

24
/**
25
 * Represents a subclass of {@link AbstractObjectPool} and implementation of
26
 * {@link BlockingObjectPool} with a defined limit of objects and a helper
27
 * to validate instances on {@link #release(java.lang.Object)}.
28
 * <p>An object failing validation is discarded, and a new one is created and
29
 * made available.
30
 * @author Swaranga
31
 * @param <T> the type of objects to pool.
32
 */
33
public final class BoundedBlockingObjectPool<T> extends AbstractObjectPool<T>
34
        implements BlockingObjectPool<T> {
35

36
    private static final Logger LOGGER = LoggerFactory.getLogger(
1✔
37
        BoundedBlockingObjectPool.class);
38

39
    private final int size;
40
    private final LinkedBlockingDeque<T> objects;
41
    private final ObjectValidator<T> validator;
42
    private final ObjectFactory<T> objectFactory;
43
    private final ExecutorService executor = Executors.newCachedThreadPool(new OpenGrokThreadFactory("bounded"));
1✔
44
    private volatile boolean puttingLast;
45
    private volatile boolean shutdownCalled;
46

47
    public BoundedBlockingObjectPool(int size, ObjectValidator<T> validator,
48
        ObjectFactory<T> objectFactory) {
1✔
49

50
        this.objectFactory = objectFactory;
1✔
51
        this.size = size;
1✔
52
        this.validator = validator;
1✔
53

54
        objects = new LinkedBlockingDeque<>(size);
1✔
55
        initializeObjects();
1✔
56
    }
1✔
57

58
    @Override
59
    public T get(long timeOut, TimeUnit unit) {
60
        if (!shutdownCalled) {
×
61
            T ret = null;
×
62
            try {
63
                ret = objects.pollFirst(timeOut, unit);
×
64
                /*
65
                 * When the queue first empties, switch to a strategy of putting
66
                 * returned objects last instead of first.
67
                 */
68
                if (!puttingLast && objects.isEmpty()) {
×
69
                    puttingLast = true;
×
70
                }
71
            } catch (InterruptedException ie) {
×
72
                Thread.currentThread().interrupt();
×
73
            }
×
74
            return ret;
×
75
        }
76
        throw new IllegalStateException("Object pool is already shutdown");
×
77
    }
78

79
    @Override
80
    public T get() {
81
        if (!shutdownCalled) {
1✔
82
            T ret = null;
1✔
83
            try {
84
                ret = objects.takeFirst();
1✔
85
                /*
86
                 * When the queue first empties, switch to a strategy of putting
87
                 * returned objects last instead of first.
88
                 */
89
                if (!puttingLast && objects.isEmpty()) {
1✔
90
                    puttingLast = true;
1✔
91
                }
92
            } catch (InterruptedException ie) {
×
93
                Thread.currentThread().interrupt();
×
94
            }
1✔
95
            return ret;
1✔
96
        }
97
        throw new IllegalStateException("Object pool is already shutdown");
×
98
    }
99

100
    @Override
101
    public void shutdown() {
102
        shutdownCalled = true;
1✔
103
        executor.shutdownNow();
1✔
104
        clearResources();
1✔
105
    }
1✔
106

107
    private void clearResources() {
108
        for (T t : objects) {
1✔
109
            validator.invalidate(t);
1✔
110
        }
1✔
111
    }
1✔
112

113
    @Override
114
    protected void returnToPool(T t) {
115
        if (validator.isValid(t)) {
1✔
116
            executor.submit(new ObjectReturner<>(objects, t, puttingLast));
1✔
117
        }
118
    }
1✔
119

120
    /*
121
     * Creates a new instance, and returns that instead to the pool.
122
     */
123
    @Override
124
    protected void handleInvalidReturn(T t) {
125
        if (LOGGER.isLoggable(Level.FINE)) {
×
126
            LOGGER.log(Level.FINE, "createNew() to handle invalid {0}",
×
127
                t.getClass());
×
128
        }
129

130
        t = objectFactory.createNew();
×
131
        executor.submit(new ObjectReturner<>(objects, t, puttingLast));
×
132
    }
×
133

134
    @Override
135
    protected boolean isValid(T t) {
136
        return validator.isValid(t);
1✔
137
    }
138

139
    private void initializeObjects() {
140
        for (int i = 0; i < size; i++) {
1✔
141
            objects.add(objectFactory.createNew());
1✔
142
        }
143
    }
1✔
144

145
    private static class ObjectReturner<E> implements Callable<Void> {
146
        private final LinkedBlockingDeque<E> queue;
147
        private final E e;
148
        private final boolean puttingLast;
149

150
        ObjectReturner(LinkedBlockingDeque<E> queue, E e, boolean puttingLast) {
1✔
151
            this.queue = queue;
1✔
152
            this.e = e;
1✔
153
            this.puttingLast = puttingLast;
1✔
154
        }
1✔
155

156
        @Override
157
        public Void call() {
158
            while (true) {
159
                try {
160
                    if (puttingLast) {
1✔
161
                        queue.putLast(e);
1✔
162
                    } else {
163
                        queue.putFirst(e);
1✔
164
                    }
165
                    break;
1✔
166
                } catch (InterruptedException ie) {
×
167
                    Thread.currentThread().interrupt();
×
168
                }
×
169
            }
170

171
            return null;
1✔
172
        }
173
    }
174
}
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

© 2026 Coveralls, Inc