Skip to content

Commit 49bfd31

Browse files
committed
Refactored FreeConnectionBuffer to use custom linked list
1 parent 8b0135b commit 49bfd31

File tree

1 file changed

+90
-16
lines changed

1 file changed

+90
-16
lines changed

ebean-datasource/src/main/java/io/ebean/datasource/pool/FreeConnectionBuffer.java

Lines changed: 90 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,52 @@
1010
*/
1111
final class FreeConnectionBuffer {
1212

13-
/**
14-
* Buffer oriented for add and remove.
15-
*/
16-
private final LinkedList<PooledConnection> freeBuffer = new LinkedList<>();
13+
14+
private final Node free = Node.init();
15+
16+
int size = 0;
1717

1818
/**
1919
* Return the number of entries in the buffer.
2020
*/
2121
int size() {
22-
return freeBuffer.size();
22+
return size;
2323
}
2424

2525
/**
2626
* Return true if the buffer is empty.
2727
*/
2828
boolean isEmpty() {
29-
return freeBuffer.isEmpty();
29+
return size == 0;
3030
}
3131

3232
/**
3333
* Add connection to the free list.
3434
*/
3535
void add(PooledConnection pc) {
36-
freeBuffer.addFirst(pc);
36+
new Node(pc).addAfter(free);
37+
size++;
3738
}
3839

3940
/**
4041
* Remove a connection from the free list.
4142
*/
4243
PooledConnection remove() {
43-
return freeBuffer.removeFirst();
44+
Node node = free.next;
45+
node.remove();
46+
size--;
47+
return node.pc;
4448
}
4549

4650
/**
4751
* Close all connections in this buffer.
4852
*/
4953
void closeAll(boolean logErrors) {
50-
List<PooledConnection> tempList = new ArrayList<>(freeBuffer);
51-
freeBuffer.clear();
54+
List<PooledConnection> tempList = new ArrayList<>();
55+
while (size > 0) {
56+
tempList.add(remove());
57+
}
58+
5259
if (Log.isLoggable(System.Logger.Level.TRACE)) {
5360
Log.trace("... closing all {0} connections from the free list with logErrors: {1}", tempList.size(), logErrors);
5461
}
@@ -62,15 +69,82 @@ void closeAll(boolean logErrors) {
6269
*/
6370
int trim(int minSize, long usedSince, long createdSince) {
6471
int trimCount = 0;
65-
ListIterator<PooledConnection> iterator = freeBuffer.listIterator(minSize);
66-
while (iterator.hasNext()) {
67-
PooledConnection pooledConnection = iterator.next();
68-
if (pooledConnection.shouldTrim(usedSince, createdSince)) {
69-
iterator.remove();
70-
pooledConnection.closeConnectionFully(true);
72+
Node node = free; // first boundary node
73+
do {
74+
node = node.next;
75+
} while (!node.isBoundaryNode() && minSize-- > 0);
76+
77+
while (!node.isBoundaryNode()) {
78+
Node current = node;
79+
node = node.next;
80+
if (current.pc.shouldTrim(usedSince, createdSince)) {
81+
current.remove();
82+
size--;
83+
current.pc.closeConnectionFully(true);
7184
trimCount++;
7285
}
7386
}
7487
return trimCount;
7588
}
89+
90+
/**
91+
* Node of a linkedlist. The linkedLists always have two empty nodes at the start and end.
92+
* (boundary nodes) They are generated with the init() method.
93+
* <p>
94+
* the first usable node is startNode.next (which could be the end edge)
95+
*/
96+
static final class Node {
97+
98+
private Node next;
99+
private Node prev;
100+
final PooledConnection pc;
101+
102+
private Node(PooledConnection pc) {
103+
this.pc = pc;
104+
}
105+
106+
/**
107+
* Creates new "list" with two empty boundary nodes
108+
*/
109+
public static Node init() {
110+
Node node1 = new Node(null);
111+
Node node2 = new Node(null);
112+
node1.next = node2;
113+
node2.prev = node1;
114+
return node1;
115+
}
116+
117+
/**
118+
* Retruns true, if this is a boundary node. (start or end node of list)
119+
*/
120+
private boolean isBoundaryNode() {
121+
return pc == null;
122+
}
123+
124+
/**
125+
* Removes the node from the list. The node can be re-added to an other list
126+
*/
127+
private void remove() {
128+
assert pc != null : "called remove a boundary node";
129+
assert prev != null && next != null : "not part of a list";
130+
next.prev = prev;
131+
prev.next = next;
132+
prev = null;
133+
next = null;
134+
}
135+
136+
/**
137+
* Adds <code>this</code> after <code>node</code>.
138+
* <p>
139+
* Node is in most cases a boundary node (e.g. start of list)
140+
*/
141+
public void addAfter(Node node) {
142+
assert !this.isBoundaryNode() : "this is a boundary node";
143+
assert next == null & prev == null : "Node already member of a list";
144+
next = node.next;
145+
prev = node;
146+
node.next.prev = this;
147+
node.next = this;
148+
}
149+
}
76150
}

0 commit comments

Comments
 (0)