package org.async.rmi.pool;
import org.async.rmi.Connection;
import org.async.rmi.Factory;
import org.async.rmi.client.ClosedException;
import org.async.rmi.messages.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Created by Barak Bar Orion
* 27/10/14.
*/
public class ShrinkableConnectionPool implements Pool<Connection<Message>> {
private static final Logger logger = LoggerFactory.getLogger(ShrinkableConnectionPool.class);
private final List<Connection<Message>> free;
private final List<Connection<Message>> all;
private final int optimalSize;
private Factory<CompletableFuture<Connection<Message>>> factory;
private boolean closed = false;
public ShrinkableConnectionPool(int optimalSize) {
this.free = new ArrayList<>();
this.all = new ArrayList<>();
this.optimalSize = optimalSize;
}
public void setFactory(Factory<CompletableFuture<Connection<Message>>> factory) {
this.factory = factory;
}
@Override
public synchronized CompletableFuture<Connection<Message>> get() {
if(closed){
throw new ClosedException();
}
if (!free.isEmpty()) {
return CompletableFuture.completedFuture(free.remove(0));
} else {
CompletableFuture<Connection<Message>> result = factory.create();
result.thenAccept(all::add);
return result;
}
}
@Override
public synchronized void free(Connection<Message> c) {
if (c.isClosed()) {
all.remove(c);
free.remove(c);
}else if (optimalSize < all.size()) {
try {
c.close();
all.remove(c);
} catch (IOException e) {
logger.warn(e.toString(), e);
}
} else {
free.add(c);
}
}
int getAllSize() {
return all.size();
}
int getFreeSize() {
return free.size();
}
@Override
public synchronized void close() throws IOException {
if(closed){
return;
}
for (Connection<Message> c : all) {
try {
c.close();
} catch (IOException e) {
logger.warn(e.toString(), e);
}
}
all.clear();
free.clear();
closed = true;
}
}