/*
* Copyright (c) 2014 Globo.com - ATeam
* All rights reserved.
*
* This source is subject to the Apache License, Version 2.0.
* Please see the LICENSE file for more information.
*
* Authors: See AUTHORS file
*
* 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 com.globo.galeb.streams;
import org.vertx.java.core.Handler;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.streams.ReadStream;
import org.vertx.java.core.streams.WriteStream;
/**
* Class Pump.
*
* @author: See AUTHORS file.
* @version: 1.0.0, Oct 22, 2014.
*/
public class Pump {
/** The ReadStream. */
private final ReadStream<?> rs;
/** The WriteStream. */
private final WriteStream<?> ws;
/** The number of bytes pumped by this pump. */
private int pumped = 0;
/** The drain handler. */
private final Handler<Void> drainHandler = new Handler<Void>() {
@Override
public synchronized void handle(Void v) {
try{
rs.resume();
} catch (RuntimeException e) {
stop();
handleException(e);
}
}
};
/** The data handler. */
private final Handler<Buffer> dataHandler = new Handler<Buffer>() {
@Override
public synchronized void handle(Buffer buffer) {
try {
ws.write(buffer);
handleWrite();
pumped += buffer.length();
if (ws.writeQueueFull()) {
rs.pause();
ws.drainHandler(drainHandler);
}
} catch (RuntimeException e) {
stop();
handleException(e);
}
}
};
/** The exception handler. */
private Handler<Throwable> exceptionHandler;
/** The write handler. */
private Handler<Void> writeHandler;
/**
* Instantiates a new pump.
*
* @param rs ReadStream
* @param ws WriteStream
*/
public Pump(ReadStream<?> rs, WriteStream<?> ws) {
this.rs = rs;
this.ws = ws;
}
/**
* Instantiates a new pump.
*
* @param rs ReadStream
* @param ws WriteStream
* @param maxWriteQueueSize the max write queue size
*/
public Pump(ReadStream<?> rs, WriteStream<?> ws, int maxWriteQueueSize) {
this(rs, ws);
this.ws.setWriteQueueMaxSize(maxWriteQueueSize);
}
/**
* Start the Pump. The Pump can be started and stopped multiple times.
*/
public void start() {
rs.dataHandler(dataHandler);
}
/**
* Stop the Pump. The Pump can be started and stopped multiple times.
*/
public void stop() {
try {
ws.drainHandler(null);
} catch (RuntimeException e) {
handleException(e);
} finally {
rs.dataHandler(null);
}
}
/**
* Return the total number of bytes pumped by this pump.
*
* @return bytes pumped
*/
public int bytesPumped() {
return this.pumped;
}
/**
* Exception handler.
*
* @param exceptionHandler the exception handler
* @return this
*/
public Pump exceptionHandler(Handler<Throwable> exceptionHandler) {
this.exceptionHandler = exceptionHandler;
return this;
}
/**
* Handle exception: invoqued when happens exceptions.
*
* @param throwable the throwable event
*/
private void handleException(Throwable throwable) {
if (exceptionHandler != null) {
exceptionHandler.handle(throwable);
}
}
/**
* Write handler.
*
* @param writeHandler the write handler
* @return this
*/
public Pump writeHandler(Handler<Void> writeHandler) {
this.writeHandler = writeHandler;
return this;
}
/**
* Handle write: invoqued when pump call WriteStream.write()
*/
private void handleWrite() {
Void voidParam = null;
if (writeHandler != null) {
writeHandler.handle(voidParam);
}
}
}