@ -228,6 +228,19 @@ public class PGStream implements Closeable, Flushable {
|
|||||||
pg_output.write(_int4buf);
|
pg_output.write(_int4buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a Long to the back end.
|
||||||
|
*
|
||||||
|
* @param val the long to be sent
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
public void sendLong(long val) throws IOException {
|
||||||
|
int high = (int)(val >> 32);
|
||||||
|
int low = (int)(val & 0xffffffff);
|
||||||
|
sendInteger4(high);
|
||||||
|
sendInteger4(low);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a 2-byte integer (short) to the back end.
|
* Sends a 2-byte integer (short) to the back end.
|
||||||
*
|
*
|
||||||
@ -327,6 +340,18 @@ public class PGStream implements Closeable, Flushable {
|
|||||||
| _int4buf[3] & 0xFF;
|
| _int4buf[3] & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives a Long from the backend.
|
||||||
|
*
|
||||||
|
* @return the 64bit integer received from the backend
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
public long receiveLong() throws IOException {
|
||||||
|
long high = receiveInteger4();
|
||||||
|
long low = receiveInteger4();
|
||||||
|
return (high << 32) | low;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives a two byte integer from the backend.
|
* Receives a two byte integer from the backend.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -90,8 +90,12 @@ public abstract class QueryExecutorBase implements QueryExecutor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void sendSupportTrace() throws IOException;
|
||||||
|
|
||||||
protected abstract void sendCloseMessage() throws IOException;
|
protected abstract void sendCloseMessage() throws IOException;
|
||||||
|
|
||||||
|
protected abstract void sendTrace() throws IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNetworkTimeout(int milliseconds) throws IOException {
|
public void setNetworkTimeout(int milliseconds) throws IOException {
|
||||||
pgStream.setNetworkTimeout(milliseconds);
|
pgStream.setNetworkTimeout(milliseconds);
|
||||||
@ -146,6 +150,7 @@ public abstract class QueryExecutorBase implements QueryExecutor {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
LOGGER.trace(" FE=> Terminate");
|
LOGGER.trace(" FE=> Terminate");
|
||||||
|
sendTrace();
|
||||||
sendCloseMessage();
|
sendCloseMessage();
|
||||||
pgStream.flush();
|
pgStream.flush();
|
||||||
pgStream.close();
|
pgStream.close();
|
||||||
|
|||||||
@ -126,6 +126,16 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
|
|
||||||
private String clientEncoding;
|
private String clientEncoding;
|
||||||
|
|
||||||
|
private long sendTime;
|
||||||
|
|
||||||
|
private long recvTime;
|
||||||
|
|
||||||
|
private long netTime;
|
||||||
|
|
||||||
|
private boolean enableTrace = false;
|
||||||
|
|
||||||
|
private boolean waitNexttime = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code CommandComplete(B)} messages are quite common, so we reuse instance to parse those
|
* {@code CommandComplete(B)} messages are quite common, so we reuse instance to parse those
|
||||||
*/
|
*/
|
||||||
@ -157,6 +167,12 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
|
|
||||||
private static final String OFF = "off";
|
private static final String OFF = "off";
|
||||||
|
|
||||||
|
private static final String SERVER_SUPPORT_TRACE = "server_support_trace";
|
||||||
|
|
||||||
|
private static final int PROTOCOL3_MSGLEN_OFFSET = 4;
|
||||||
|
|
||||||
|
private static final int TIME_NS_ONE_US = 1000;
|
||||||
|
|
||||||
public QueryExecutorImpl(PGStream pgStream, String user, String database,
|
public QueryExecutorImpl(PGStream pgStream, String user, String database,
|
||||||
int cancelSignalTimeout, Properties info) throws SQLException, IOException {
|
int cancelSignalTimeout, Properties info) throws SQLException, IOException {
|
||||||
super(pgStream, user, database, cancelSignalTimeout, info);
|
super(pgStream, user, database, cancelSignalTimeout, info);
|
||||||
@ -222,6 +238,14 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
return this.clientEncoding;
|
return this.clientEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getWaitNexttime() {
|
||||||
|
return waitNexttime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWaitNexttime(boolean waitNexttime) {
|
||||||
|
this.waitNexttime = waitNexttime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When database compatibility mode is A database and the parameter overload function
|
* When database compatibility mode is A database and the parameter overload function
|
||||||
* is turned on, add out parameter description message.
|
* is turned on, add out parameter description message.
|
||||||
@ -294,6 +318,14 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recordSendTime() {
|
||||||
|
sendTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recordRecvTime() {
|
||||||
|
recvTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param holder object assumed to hold the lock
|
* @param holder object assumed to hold the lock
|
||||||
* @return whether given object actually holds the lock
|
* @return whether given object actually holds the lock
|
||||||
@ -363,6 +395,10 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSimpleQuery(int flags) {
|
||||||
|
return (flags & QueryExecutor.QUERY_EXECUTE_AS_SIMPLE) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void execute(Query query, ParameterList parameters, ResultHandler handler,
|
public synchronized void execute(Query query, ParameterList parameters, ResultHandler handler,
|
||||||
int maxRows, int fetchSize, int flags) throws SQLException {
|
int maxRows, int fetchSize, int flags) throws SQLException {
|
||||||
waitOnLock();
|
waitOnLock();
|
||||||
@ -388,6 +424,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
boolean autosave = false;
|
boolean autosave = false;
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
|
recordAndSendTrace(flags);
|
||||||
handler = sendQueryPreamble(handler, flags);
|
handler = sendQueryPreamble(handler, flags);
|
||||||
autosave = sendAutomaticSavepoint(query, flags);
|
autosave = sendAutomaticSavepoint(query, flags);
|
||||||
sendQuery(query, (V3ParameterList) parameters, maxRows, fetchSize, flags,
|
sendQuery(query, (V3ParameterList) parameters, maxRows, fetchSize, flags,
|
||||||
@ -546,6 +583,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
boolean autosave = false;
|
boolean autosave = false;
|
||||||
ResultHandler handler = batchHandler;
|
ResultHandler handler = batchHandler;
|
||||||
try {
|
try {
|
||||||
|
recordAndSendTrace(flags);
|
||||||
handler = sendQueryPreamble(batchHandler, flags);
|
handler = sendQueryPreamble(batchHandler, flags);
|
||||||
autosave = sendAutomaticSavepoint(queries[0], flags);
|
autosave = sendAutomaticSavepoint(queries[0], flags);
|
||||||
estimatedReceiveBufferBytes = 0;
|
estimatedReceiveBufferBytes = 0;
|
||||||
@ -619,6 +657,8 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
boolean autosave = false;
|
boolean autosave = false;
|
||||||
ResultHandler handler = batchHandler;
|
ResultHandler handler = batchHandler;
|
||||||
try {
|
try {
|
||||||
|
// P->DS->S U->E->S
|
||||||
|
recordAndSendTrace(flags);
|
||||||
handler = sendQueryPreamble(batchHandler, flags);
|
handler = sendQueryPreamble(batchHandler, flags);
|
||||||
autosave = sendAutomaticSavepoint(queries[0], flags);
|
autosave = sendAutomaticSavepoint(queries[0], flags);
|
||||||
estimatedReceiveBufferBytes = 0;
|
estimatedReceiveBufferBytes = 0;
|
||||||
@ -748,6 +788,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
recordAndSendTrace(QueryExecutor.QUERY_NO_METADATA);
|
||||||
sendOneQuery(beginTransactionQuery, SimpleQuery.NO_PARAMETERS, 0, 0,
|
sendOneQuery(beginTransactionQuery, SimpleQuery.NO_PARAMETERS, 0, 0,
|
||||||
QueryExecutor.QUERY_NO_METADATA);
|
QueryExecutor.QUERY_NO_METADATA);
|
||||||
sendSync();
|
sendSync();
|
||||||
@ -1564,6 +1605,28 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// record sendTime and send K message.
|
||||||
|
//
|
||||||
|
private void recordAndSendTrace(int flags) throws IOException {
|
||||||
|
if (!isSimpleQuery(flags)) {
|
||||||
|
recordSendTime();
|
||||||
|
}
|
||||||
|
sendTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// send netTime to database
|
||||||
|
//
|
||||||
|
protected void sendTrace() throws IOException {
|
||||||
|
if (!enableTrace) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pgStream.sendChar('K'); // Sync
|
||||||
|
pgStream.sendInteger4(8 + PROTOCOL3_MSGLEN_OFFSET); // Length
|
||||||
|
pgStream.sendLong(netTime);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Message sending
|
// Message sending
|
||||||
//
|
//
|
||||||
@ -2142,11 +2205,12 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
//
|
//
|
||||||
private void sendOneQuery(SimpleQuery query, SimpleParameterList params, int maxRows,
|
private void sendOneQuery(SimpleQuery query, SimpleParameterList params, int maxRows,
|
||||||
int fetchSize, int flags) throws IOException {
|
int fetchSize, int flags) throws IOException {
|
||||||
boolean asSimple = (flags & QueryExecutor.QUERY_EXECUTE_AS_SIMPLE) != 0;
|
boolean asSimple = isSimpleQuery(flags);
|
||||||
if (asSimple) {
|
if (asSimple) {
|
||||||
assert (flags & QueryExecutor.QUERY_DESCRIBE_ONLY) == 0
|
assert (flags & QueryExecutor.QUERY_DESCRIBE_ONLY) == 0
|
||||||
: "Simple mode does not support describe requests. sql = " + query.getNativeSql()
|
: "Simple mode does not support describe requests. sql = " + query.getNativeSql()
|
||||||
+ ", flags = " + flags;
|
+ ", flags = " + flags;
|
||||||
|
recordSendTime();
|
||||||
sendSimpleQuery(query, params);
|
sendSimpleQuery(query, params);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2445,10 +2509,25 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
// from there.
|
// from there.
|
||||||
boolean doneAfterRowDescNoData = false;
|
boolean doneAfterRowDescNoData = false;
|
||||||
try {
|
try {
|
||||||
|
boolean isRecvP = false;
|
||||||
while (!endQuery) {
|
while (!endQuery) {
|
||||||
c = pgStream.receiveChar();
|
c = pgStream.receiveChar();
|
||||||
recievedPacketType=c;
|
recievedPacketType=c;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'K': //receive dbTime
|
||||||
|
recordRecvTime();
|
||||||
|
int msgLen = pgStream.receiveInteger4();
|
||||||
|
// dbTime 8 bytes
|
||||||
|
assert (msgLen == 8 + PROTOCOL3_MSGLEN_OFFSET);
|
||||||
|
long dbTime = pgStream.receiveLong();
|
||||||
|
if (getWaitNexttime()) {
|
||||||
|
netTime += ((recvTime - sendTime) / TIME_NS_ONE_US) - dbTime;
|
||||||
|
} else {
|
||||||
|
netTime = ((recvTime - sendTime) / TIME_NS_ONE_US) - dbTime;
|
||||||
|
}
|
||||||
|
isRecvP = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'A': // Asynchronous Notify
|
case 'A': // Asynchronous Notify
|
||||||
receiveAsyncNotify();
|
receiveAsyncNotify();
|
||||||
break;
|
break;
|
||||||
@ -2836,7 +2915,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
throw new IOException("Unexpected packet type: " + c);
|
throw new IOException("Unexpected packet type: " + c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enableTrace = isRecvP;
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
LOGGER.error("IO Exception.recieved packetType:" + recievedPacketType + "last PacketType:" + lastPacketType
|
LOGGER.error("IO Exception.recieved packetType:" + recievedPacketType + "last PacketType:" + lastPacketType
|
||||||
+ "connection info:" + secSocketAddress + "buffer :\n" + pgStream.getInputBufferByHex());
|
+ "connection info:" + secSocketAddress + "buffer :\n" + pgStream.getInputBufferByHex());
|
||||||
@ -2877,6 +2956,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
processDeadParsedQueries();
|
processDeadParsedQueries();
|
||||||
processDeadPortals();
|
processDeadPortals();
|
||||||
|
|
||||||
|
recordAndSendTrace(0);
|
||||||
sendExecute(portal.getQuery(), portal, fetchSize);
|
sendExecute(portal.getQuery(), portal, fetchSize);
|
||||||
sendSync();
|
sendSync();
|
||||||
|
|
||||||
@ -3059,6 +3139,12 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void sendSupportTrace() throws IOException {
|
||||||
|
pgStream.sendChar('V');
|
||||||
|
pgStream.sendInteger4(4);
|
||||||
|
pgStream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void sendCloseMessage() throws IOException {
|
protected void sendCloseMessage() throws IOException {
|
||||||
pgStream.sendChar('X');
|
pgStream.sendChar('X');
|
||||||
@ -3125,6 +3211,13 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
String name = pgStream.receiveString();
|
String name = pgStream.receiveString();
|
||||||
String value = pgStream.receiveString();
|
String value = pgStream.receiveString();
|
||||||
|
|
||||||
|
if (name.equals(SERVER_SUPPORT_TRACE)) {
|
||||||
|
// SERVER_SUPPORT_TRACE equals "1" means server support trace
|
||||||
|
if ("1".equals(value)) {
|
||||||
|
sendSupportTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (name.equals(CLIENT_ENCODING)) {
|
if (name.equals(CLIENT_ENCODING)) {
|
||||||
if (allowEncodingChanges) {
|
if (allowEncodingChanges) {
|
||||||
if (!value.equalsIgnoreCase("UTF8") && !value.equalsIgnoreCase("GBK")) {
|
if (!value.equalsIgnoreCase("UTF8") && !value.equalsIgnoreCase("GBK")) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ package org.postgresql.jdbc;
|
|||||||
|
|
||||||
import org.postgresql.Driver;
|
import org.postgresql.Driver;
|
||||||
import org.postgresql.core.*;
|
import org.postgresql.core.*;
|
||||||
|
import org.postgresql.core.v3.QueryExecutorImpl;
|
||||||
import org.postgresql.quickautobalance.ConnectionManager;
|
import org.postgresql.quickautobalance.ConnectionManager;
|
||||||
import org.postgresql.quickautobalance.LoadBalanceHeartBeating;
|
import org.postgresql.quickautobalance.LoadBalanceHeartBeating;
|
||||||
import org.postgresql.util.GT;
|
import org.postgresql.util.GT;
|
||||||
@ -991,6 +992,7 @@ public class PgStatement implements Statement, BaseStatement {
|
|||||||
BatchResultHandler handler;
|
BatchResultHandler handler;
|
||||||
handler = createBatchHandler(queries, parameterLists);
|
handler = createBatchHandler(queries, parameterLists);
|
||||||
|
|
||||||
|
QueryExecutorImpl executer = (QueryExecutorImpl) connection.getQueryExecutor();
|
||||||
if ((preDescribe || forceBinaryTransfers)
|
if ((preDescribe || forceBinaryTransfers)
|
||||||
&& (flags & QueryExecutor.QUERY_EXECUTE_AS_SIMPLE) == 0) {
|
&& (flags & QueryExecutor.QUERY_EXECUTE_AS_SIMPLE) == 0) {
|
||||||
// Do a client-server round trip, parsing and describing the query so we
|
// Do a client-server round trip, parsing and describing the query so we
|
||||||
@ -1000,6 +1002,9 @@ public class PgStatement implements Statement, BaseStatement {
|
|||||||
StatementResultHandler handler2 = new StatementResultHandler();
|
StatementResultHandler handler2 = new StatementResultHandler();
|
||||||
try {
|
try {
|
||||||
connection.getQueryExecutor().execute(queries[0], parameterLists[0], handler2, 0, 0, flags2);
|
connection.getQueryExecutor().execute(queries[0], parameterLists[0], handler2, 0, 0, flags2);
|
||||||
|
if (connection.getQueryExecutor() instanceof QueryExecutorImpl) {
|
||||||
|
executer.setWaitNexttime(true);
|
||||||
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
// Unable to parse the first statement -> throw BatchUpdateException
|
// Unable to parse the first statement -> throw BatchUpdateException
|
||||||
handler.handleError(e);
|
handler.handleError(e);
|
||||||
@ -1046,6 +1051,7 @@ public class PgStatement implements Statement, BaseStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
executer.setWaitNexttime(false);
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user