
org.apache.zookeeper.server.ServerCnxn Maven / Gradle / Ivy
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zookeeper.server;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.jute.Record;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.proto.ReplyHeader;
import org.apache.zookeeper.proto.RequestHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Interface to a Server connection - represents a connection from a client
* to the server.
*/
public abstract class ServerCnxn implements Stats, Watcher {
// This is just an arbitrary object to represent requests issued by
// (aka owned by) this class
final public static Object me = new Object();
private static final Logger LOG = LoggerFactory.getLogger(ServerCnxn.class);
protected ArrayList authInfo = new ArrayList();
/**
* If the client is of old version, we don't send r-o mode info to it.
* The reason is that if we would, old C client doesn't read it, which
* results in TCP RST packet, i.e. "connection reset by peer".
*/
boolean isOldClient = true;
abstract int getSessionTimeout();
abstract void close();
public abstract void sendResponse(ReplyHeader h, Record r, String tag)
throws IOException;
/* notify the client the session is closing and close/cleanup socket */
abstract void sendCloseSession();
public abstract void process(WatchedEvent event);
public abstract long getSessionId();
abstract void setSessionId(long sessionId);
/** auth info for the cnxn, returns an unmodifyable list */
public List getAuthInfo() {
return Collections.unmodifiableList(authInfo);
}
public void addAuthInfo(Id id) {
if (authInfo.contains(id) == false) {
authInfo.add(id);
}
}
public boolean removeAuthInfo(Id id) {
return authInfo.remove(id);
}
abstract void sendBuffer(ByteBuffer closeConn);
abstract void enableRecv();
abstract void disableRecv();
abstract void setSessionTimeout(int sessionTimeout);
protected ZooKeeperSaslServer zooKeeperSaslServer = null;
protected static class CloseRequestException extends IOException {
private static final long serialVersionUID = -7854505709816442681L;
public CloseRequestException(String msg) {
super(msg);
}
}
protected static class EndOfStreamException extends IOException {
private static final long serialVersionUID = -8255690282104294178L;
public EndOfStreamException(String msg) {
super(msg);
}
public String toString() {
return "EndOfStreamException: " + getMessage();
}
}
protected void packetReceived() {
incrPacketsReceived();
ServerStats serverStats = serverStats();
if (serverStats != null) {
serverStats().incrementPacketsReceived();
}
}
protected void packetSent() {
incrPacketsSent();
ServerStats serverStats = serverStats();
if (serverStats != null) {
serverStats().incrementPacketsSent();
}
}
protected abstract ServerStats serverStats();
protected final Date established = new Date();
protected final AtomicLong packetsReceived = new AtomicLong();
protected final AtomicLong packetsSent = new AtomicLong();
protected long minLatency;
protected long maxLatency;
protected String lastOp;
protected long lastCxid;
protected long lastZxid;
protected long lastResponseTime;
protected long lastLatency;
protected long count;
protected long totalLatency;
public synchronized void resetStats() {
packetsReceived.set(0);
packetsSent.set(0);
minLatency = Long.MAX_VALUE;
maxLatency = 0;
lastOp = "NA";
lastCxid = -1;
lastZxid = -1;
lastResponseTime = 0;
lastLatency = 0;
count = 0;
totalLatency = 0;
}
protected long incrPacketsReceived() {
return packetsReceived.incrementAndGet();
}
protected void incrOutstandingRequests(RequestHeader h) {
}
protected long incrPacketsSent() {
return packetsSent.incrementAndGet();
}
protected synchronized void updateStatsForResponse(long cxid, long zxid,
String op, long start, long end)
{
// don't overwrite with "special" xids - we're interested
// in the clients last real operation
if (cxid >= 0) {
lastCxid = cxid;
}
lastZxid = zxid;
lastOp = op;
lastResponseTime = end;
long elapsed = end - start;
lastLatency = elapsed;
if (elapsed < minLatency) {
minLatency = elapsed;
}
if (elapsed > maxLatency) {
maxLatency = elapsed;
}
count++;
totalLatency += elapsed;
}
public Date getEstablished() {
return (Date)established.clone();
}
public abstract long getOutstandingRequests();
public long getPacketsReceived() {
return packetsReceived.longValue();
}
public long getPacketsSent() {
return packetsSent.longValue();
}
public synchronized long getMinLatency() {
return minLatency == Long.MAX_VALUE ? 0 : minLatency;
}
public synchronized long getAvgLatency() {
return count == 0 ? 0 : totalLatency / count;
}
public synchronized long getMaxLatency() {
return maxLatency;
}
public synchronized String getLastOperation() {
return lastOp;
}
public synchronized long getLastCxid() {
return lastCxid;
}
public synchronized long getLastZxid() {
return lastZxid;
}
public synchronized long getLastResponseTime() {
return lastResponseTime;
}
public synchronized long getLastLatency() {
return lastLatency;
}
/**
* Prints detailed stats information for the connection.
*
* @see dumpConnectionInfo(PrintWriter, boolean) for brief stats
*/
@Override
public String toString() {
StringWriter sw = new StringWriter();
PrintWriter pwriter = new PrintWriter(sw);
dumpConnectionInfo(pwriter, false);
pwriter.flush();
pwriter.close();
return sw.toString();
}
public abstract InetSocketAddress getRemoteSocketAddress();
public abstract int getInterestOps();
public abstract boolean isSecure();
public abstract Certificate[] getClientCertificateChain();
public abstract void setClientCertificateChain(Certificate[] chain);
/**
* Print information about the connection.
* @param brief iff true prints brief details, otw full detail
* @return information about this connection
*/
public synchronized void
dumpConnectionInfo(PrintWriter pwriter, boolean brief) {
pwriter.print(" ");
pwriter.print(getRemoteSocketAddress());
pwriter.print("[");
int interestOps = getInterestOps();
pwriter.print(interestOps == 0 ? "0" : Integer.toHexString(interestOps));
pwriter.print("](queued=");
pwriter.print(getOutstandingRequests());
pwriter.print(",recved=");
pwriter.print(getPacketsReceived());
pwriter.print(",sent=");
pwriter.print(getPacketsSent());
if (!brief) {
long sessionId = getSessionId();
if (sessionId != 0) {
pwriter.print(",sid=0x");
pwriter.print(Long.toHexString(sessionId));
pwriter.print(",lop=");
pwriter.print(getLastOperation());
pwriter.print(",est=");
pwriter.print(getEstablished().getTime());
pwriter.print(",to=");
pwriter.print(getSessionTimeout());
long lastCxid = getLastCxid();
if (lastCxid >= 0) {
pwriter.print(",lcxid=0x");
pwriter.print(Long.toHexString(lastCxid));
}
pwriter.print(",lzxid=0x");
pwriter.print(Long.toHexString(getLastZxid()));
pwriter.print(",lresp=");
pwriter.print(getLastResponseTime());
pwriter.print(",llat=");
pwriter.print(getLastLatency());
pwriter.print(",minlat=");
pwriter.print(getMinLatency());
pwriter.print(",avglat=");
pwriter.print(getAvgLatency());
pwriter.print(",maxlat=");
pwriter.print(getMaxLatency());
}
}
pwriter.print(")");
}
public synchronized Map getConnectionInfo(boolean brief) {
Map info = new LinkedHashMap();
info.put("remote_socket_address", getRemoteSocketAddress());
info.put("interest_ops", getInterestOps());
info.put("outstanding_requests", getOutstandingRequests());
info.put("packets_received", getPacketsReceived());
info.put("packets_sent", getPacketsSent());
if (!brief) {
info.put("session_id", getSessionId());
info.put("last_operation", getLastOperation());
info.put("established", getEstablished());
info.put("session_timeout", getSessionTimeout());
info.put("last_cxid", getLastCxid());
info.put("last_zxid", getLastZxid());
info.put("last_response_time", getLastResponseTime());
info.put("last_latency", getLastLatency());
info.put("min_latency", getMinLatency());
info.put("avg_latency", getAvgLatency());
info.put("max_latency", getMaxLatency());
}
return info;
}
/**
* clean up the socket related to a command and also make sure we flush the
* data before we do that
*
* @param pwriter
* the pwriter for a command socket
*/
public void cleanupWriterSocket(PrintWriter pwriter) {
try {
if (pwriter != null) {
pwriter.flush();
pwriter.close();
}
} catch (Exception e) {
LOG.info("Error closing PrintWriter ", e);
} finally {
try {
close();
} catch (Exception e) {
LOG.error("Error closing a command socket ", e);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy