All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.redkale.source.PoolTcpSource Maven / Gradle / Ivy
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.source;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.sql.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import org.redkale.net.AsyncConnection;
import static org.redkale.source.DataSources.*;
import org.redkale.util.ObjectPool;
/**
*
* @author zhangjx
*/
public abstract class PoolTcpSource extends PoolSource {
//ByteBuffer池
protected ObjectPool bufferPool;
//线程池
protected ThreadPoolExecutor executor;
//供supplyAsync->poll使用的线程池
protected ExecutorService pollExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 4, (r) -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});
//TCP Channel组
protected AsynchronousChannelGroup group;
protected final ArrayBlockingQueue connQueue;
public PoolTcpSource(String rwtype, ArrayBlockingQueue queue, Semaphore semaphore, Properties prop, Logger logger, ObjectPool bufferPool, ThreadPoolExecutor executor) {
super(rwtype, semaphore, prop, logger);
this.bufferPool = bufferPool;
this.executor = executor;
try {
this.group = AsynchronousChannelGroup.withThreadPool(executor);
} catch (IOException e) {
throw new RuntimeException(e);
}
this.connQueue = queue == null ? new ArrayBlockingQueue<>(this.maxconns) : queue;
}
@Override
public void offerConnection(final AsyncConnection conn) {
if (conn == null) return;
if (conn.isOpen() && connQueue.offer(conn)) {
saveCounter.incrementAndGet();
usingCounter.decrementAndGet();
} else {
//usingCounter 会在close方法中执行
CompletableFuture future = null;
try {
future = sendCloseCommand(conn);
} catch (Exception e) {
}
if (future == null) {
conn.dispose();
} else {
future.whenComplete((c, t) -> {
if (c != null) c.dispose();
});
}
}
}
@Override
public void change(Properties prop) {
String newurl = prop.getProperty(JDBC_URL, this.url);
String newuser = prop.getProperty(JDBC_USER, this.username);
String newpassword = prop.getProperty(JDBC_PWD, this.password);
if (Objects.equals(this.url, newurl) && Objects.equals(this.username, newuser) && Objects.equals(this.password, newpassword)) return;
this.url = newurl;
this.username = newuser;
this.password = newpassword;
parseAddressAndDbnameAndAttrs();
}
@Override
public final AsyncConnection poll() {
return pollAsync().join();
}
protected abstract ByteBuffer reqConnectBuffer(AsyncConnection conn);
protected abstract void respConnectBuffer(final ByteBuffer buffer, CompletableFuture future, AsyncConnection conn);
@Override
public CompletableFuture pollAsync() {
return pollAsync(0);
}
protected CompletableFuture pollAsync(final int count) {
if (count >= 5) {
logger.log(Level.WARNING, "create datasource connection error");
CompletableFuture future = new CompletableFuture<>();
future.completeExceptionally(new SQLException("create datasource connection error"));
return future;
}
AsyncConnection conn0 = connQueue.poll();
if (conn0 != null && conn0.isOpen()) {
cycleCounter.incrementAndGet();
usingCounter.incrementAndGet();
return CompletableFuture.completedFuture(conn0);
}
if (!semaphore.tryAcquire()) {
return CompletableFuture.supplyAsync(() -> {
try {
return connQueue.poll(1, TimeUnit.SECONDS);
} catch (Exception t) {
return null;
}
}, pollExecutor).thenCompose((conn2) -> {
if (conn2 != null && conn2.isOpen()) {
cycleCounter.incrementAndGet();
usingCounter.incrementAndGet();
return CompletableFuture.completedFuture(conn2);
}
return pollAsync(count + 1);
});
}
return AsyncConnection.createTCP(group, this.servaddr, this.readTimeoutSeconds, this.writeTimeoutSeconds).thenCompose(conn -> {
conn.beforeCloseListener((c) -> {
semaphore.release();
closeCounter.incrementAndGet();
usingCounter.decrementAndGet();
});
CompletableFuture future = new CompletableFuture();
final ByteBuffer buffer = reqConnectBuffer(conn);
if (buffer == null) {
final ByteBuffer rbuffer = bufferPool.get();
conn.read(rbuffer, null, new CompletionHandler() {
@Override
public void completed(Integer result, Void attachment2) {
if (result < 0) {
failed(new SQLException("Read Buffer Error"), attachment2);
return;
}
rbuffer.flip();
respConnectBuffer(rbuffer, future, conn);
}
@Override
public void failed(Throwable exc, Void attachment2) {
bufferPool.accept(rbuffer);
future.completeExceptionally(exc);
conn.dispose();
}
});
} else {
conn.write(buffer, null, new CompletionHandler() {
@Override
public void completed(Integer result, Void attachment1) {
if (result < 0) {
failed(new SQLException("Write Buffer Error"), attachment1);
return;
}
if (buffer.hasRemaining()) {
conn.write(buffer, attachment1, this);
return;
}
buffer.clear();
conn.read(buffer, null, new CompletionHandler() {
@Override
public void completed(Integer result, Void attachment2) {
if (result < 0) {
failed(new SQLException("Read Buffer Error"), attachment2);
return;
}
buffer.flip();
respConnectBuffer(buffer, future, conn);
}
@Override
public void failed(Throwable exc, Void attachment2) {
bufferPool.accept(buffer);
future.completeExceptionally(exc);
conn.dispose();
}
});
}
@Override
public void failed(Throwable exc, Void attachment1) {
bufferPool.accept(buffer);
future.completeExceptionally(exc);
conn.dispose();
}
});
}
return future;
}).whenComplete((c, t) -> {
if (t == null) {
creatCounter.incrementAndGet();
usingCounter.incrementAndGet();
} else {
semaphore.release();
}
});
}
@Override
public void close() {
connQueue.stream().forEach(x -> {
CompletableFuture future = null;
try {
future = sendCloseCommand(x);
} catch (Exception e) {
}
if (future == null) {
x.dispose();
} else {
future.whenComplete((c, t) -> {
if (c != null) c.dispose();
});
}
});
}
protected abstract CompletableFuture sendCloseCommand(final AsyncConnection conn);
}