org.apache.rocketmq.shaded.ch.qos.logback.core.net.server.RemoteReceiverStreamClient Maven / Gradle / Ivy
/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package org.apache.rocketmq.shaded.ch.qos.logback.core.net.server;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.BlockingQueue;
import org.apache.rocketmq.shaded.ch.qos.logback.core.CoreConstants;
import org.apache.rocketmq.shaded.ch.qos.logback.core.spi.ContextAwareBase;
import org.apache.rocketmq.shaded.ch.qos.logback.core.util.CloseUtil;
/**
* A {@link RemoteReceiverClient} that writes serialized logging events to an
* {@link OutputStream}.
*
* @author Carl Harris
*/
class RemoteReceiverStreamClient extends ContextAwareBase implements RemoteReceiverClient {
private final String clientId;
private final Socket socket;
private final OutputStream outputStream;
private BlockingQueue queue;
/**
* Constructs a new client.
* @param id identifier string for the client
* @param socket socket to which logging events will be written
*/
public RemoteReceiverStreamClient(String id, Socket socket) {
this.clientId = "client " + id + ": ";
this.socket = socket;
this.outputStream = null;
}
/**
* Constructs a new client.
*
* This constructor exists primarily to support unit tests where it
* is inconvenient to have to create a socket for the test.
*
* @param id identifier string for the client
* @param outputStream output stream to which logging Events will be written
*/
RemoteReceiverStreamClient(String id, OutputStream outputStream) {
this.clientId = "client " + id + ": ";
this.socket = null;
this.outputStream = outputStream;
}
/**
* {@inheritDoc}
*/
public void setQueue(BlockingQueue queue) {
this.queue = queue;
}
/**
* {@inheritDoc}
*/
public boolean offer(Serializable event) {
if (queue == null) {
throw new IllegalStateException("client has no event queue");
}
return queue.offer(event);
}
/**
* {@inheritDoc}
*/
public void close() {
if (socket == null)
return;
CloseUtil.closeQuietly(socket);
}
/**
* {@inheritDoc}
*/
public void run() {
addInfo(clientId + "connected");
ObjectOutputStream oos = null;
try {
int counter = 0;
oos = createObjectOutputStream();
while (!Thread.currentThread().isInterrupted()) {
try {
Serializable event = queue.take();
oos.writeObject(event);
oos.flush();
if (++counter >= CoreConstants.OOS_RESET_FREQUENCY) {
// failing to reset the stream periodically will result in a
// serious memory leak (as noted in AbstractSocketAppender)
counter = 0;
oos.reset();
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
} catch (SocketException ex) {
addInfo(clientId + ex);
} catch (IOException ex) {
addError(clientId + ex);
} catch (RuntimeException ex) {
addError(clientId + ex);
} finally {
if (oos != null) {
CloseUtil.closeQuietly(oos);
}
close();
addInfo(clientId + "connection closed");
}
}
private ObjectOutputStream createObjectOutputStream() throws IOException {
if (socket == null) {
return new ObjectOutputStream(outputStream);
}
return new ObjectOutputStream(socket.getOutputStream());
}
}