package com.datastax.oss.driver.internal.core.pool;
import com.datastax.oss.driver.internal.core.channel.DriverChannel;
import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
import com.datastax.oss.driver.shaded.guava.common.collect.Iterators;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.locks.ReentrantLock;
import net.jcip.annotations.ThreadSafe;
@ThreadSafe
class ChannelSet implements Iterable<DriverChannel> {
private volatile DriverChannel[] channels;
private final ReentrantLock lock = new ReentrantLock();
ChannelSet() {
this.channels = new DriverChannel[] {};
}
void add(DriverChannel toAdd) {
Preconditions.checkNotNull(toAdd);
lock.lock();
try {
assert indexOf(channels, toAdd) < 0;
DriverChannel[] newChannels = Arrays.copyOf(channels, channels.length + 1);
newChannels[newChannels.length - 1] = toAdd;
channels = newChannels;
} finally {
lock.unlock();
}
}
boolean remove(DriverChannel toRemove) {
Preconditions.checkNotNull(toRemove);
lock.lock();
try {
int index = indexOf(channels, toRemove);
if (index < 0) {
return false;
} else {
DriverChannel[] newChannels = new DriverChannel[channels.length - 1];
int newI = 0;
for (int i = 0; i < channels.length; i++) {
if (i != index) {
newChannels[newI] = channels[i];
newI += 1;
}
}
channels = newChannels;
return true;
}
} finally {
lock.unlock();
}
}
DriverChannel next() {
DriverChannel[] snapshot = this.channels;
switch (snapshot.length) {
case 0:
return null;
case 1:
return snapshot[0];
default:
DriverChannel best = null;
int bestScore = 0;
for (DriverChannel channel : snapshot) {
int score = channel.getAvailableIds();
if (score > bestScore) {
bestScore = score;
best = channel;
}
}
return best;
}
}
int getAvailableIds() {
int availableIds = 0;
DriverChannel[] snapshot = this.channels;
for (DriverChannel channel : snapshot) {
availableIds += channel.getAvailableIds();
}
return availableIds;
}
int getInFlight() {
int inFlight = 0;
DriverChannel[] snapshot = this.channels;
for (DriverChannel channel : snapshot) {
inFlight += channel.getInFlight();
}
return inFlight;
}
int getOrphanedIds() {
int orphanedIds = 0;
DriverChannel[] snapshot = this.channels;
for (DriverChannel channel : snapshot) {
orphanedIds += channel.getOrphanedIds();
}
return orphanedIds;
}
int size() {
return this.channels.length;
}
@NonNull
@Override
public Iterator<DriverChannel> iterator() {
return Iterators.forArray(this.channels);
}
private static int indexOf(DriverChannel[] channels, DriverChannel key) {
for (int i = 0; i < channels.length; i++) {
if (channels[i] == key) {
return i;
}
}
return -1;
}
}