use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class BasChannelImpl method unqueueAndFailWritesThenClose.
private void unqueueAndFailWritesThenClose(CloseRunnable action) {
List<XFuture<Void>> promises;
synchronized (this) {
// put here for emphasis that we are synchronizing here but not below
promises = failAllWritesInQueue();
}
// TODO: This should really be inlined now. It's a remnant of an old design since close didn't
// work well outside the selector thread previously
action.runDelayedAction();
// notify clients outside the synchronization block!!!
for (XFuture<Void> promise : promises) {
log.info("WRITES outstanding while close was called, notifying client through his failure method of the exception");
// we only incur the cost of Throwable.fillInStackTrace() if we will use this exception
// (it's called in the Throwable constructor) so we don't do this on every close channel
NioClosedChannelException closeExc = new NioClosedChannelException(this + "There are " + promises.size() + " writes that are not complete yet(you called write but " + "they did not call success back to the client).");
promise.completeExceptionally(closeExc);
}
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class BasChannelImpl method writeAll.
/**
* This method is reading from the queue and writing out to the socket buffers that
* did not get written out when client called write.
*/
void writeAll() {
List<XFuture<Void>> finishedPromises = new ArrayList<>();
synchronized (writeLock) {
if (dataToBeWritten.isEmpty())
throw new IllegalStateException(this + "bug, I am not sure this is possible..it shouldn't be...look into");
while (!dataToBeWritten.isEmpty()) {
WriteInfo writer = dataToBeWritten.peek();
ByteBuffer buffer = writer.getBuffer();
int initialSize = buffer.remaining();
int wroteOut = this.writeImpl(buffer);
if (buffer.hasRemaining()) {
if (buffer.remaining() + wroteOut != initialSize)
throw new IllegalStateException(this + "Something went wrong. b.remaining()=" + buffer.remaining() + " written=" + wroteOut + " total=" + initialSize);
if (log.isTraceEnabled())
log.trace(this + "Did not write all data out");
int leftOverSize = buffer.remaining();
int writtenOut = initialSize - leftOverSize;
waitingBytesCounter -= writtenOut;
break;
}
// if it finished, remove the item from the queue. It
// does not need to be run again.
dataToBeWritten.poll();
waitingBytesCounter -= initialSize;
finishedPromises.add(writer.getPromise());
}
// we are registered for writes with ANY size queue
if (dataToBeWritten.isEmpty() && inDelayedWriteMode) {
inDelayedWriteMode = false;
if (log.isTraceEnabled())
log.trace(this + "unregister writes");
router.unregisterSelectableChannel(this, SelectionKey.OP_WRITE);
}
}
// MAKE SURE to notify clients outside of synchronization block so no deadlocks with their locks
for (XFuture<Void> promise : finishedPromises) {
promise.complete(null);
}
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class BasChannelImpl method failAllWritesInQueue.
// synchronized with writeAll as both try to go through every element in the queue
// while most of the time there will be no contention(only on the close do we hit this)
private synchronized List<XFuture<Void>> failAllWritesInQueue() {
List<XFuture<Void>> copy = new ArrayList<>();
while (!dataToBeWritten.isEmpty()) {
WriteInfo runnable = dataToBeWritten.remove();
ByteBuffer buffer = runnable.getBuffer();
// mark buffer read before releasing it
buffer.position(buffer.limit());
pool.releaseBuffer(buffer);
copy.add(runnable.getPromise());
}
waitingBytesCounter = 0;
return copy;
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class Level2ParsingAndRemoteSettings method parseImpl.
public XFuture<Void> parseImpl(DataWrapper newData) {
parsingState = lowLevelParser.unmarshal(parsingState, newData);
List<Http2Msg> parsedMessages = parsingState.getParsedFrames();
// All the below futures must be chained with previous ones in case previous ones are not
// done which will serialize it all to be in sequence
XFuture<Void> future = parsingState.getProcessFuture();
for (Http2Msg lowLevelFrame : parsedMessages) {
// VERY IMPORTANT: Writing the code like this would slam through calling process N times
// BUT it doesn't give the clients a chance to seet a flag between packets
// Mainly done for exceptions and streaming so you can log exc, set a boolean so you
// don't get 100 exceptions while something is happening like socket disconnect
// In these 2 lines of code, processCorrectly is CALLED N times RIGHT NOW
// The code below this only calls them right now IF AND ONLY IF the client returns
// a completed future each time!!!
// XFuture<Void> messageFuture = process(lowLevelFrame);
// allFutures = allFutures.thenCompose( f -> messageFuture);
future = future.thenCompose(f -> process(lowLevelFrame));
}
parsingState.setProcessFuturee(future);
return future;
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class Level5AStates method translateException.
private XFuture<Void> translateException(Stream stream, Throwable t) {
XFuture<Void> fut = new XFuture<>();
if (t instanceof NoTransitionConnectionError)
fut.completeExceptionally(new ConnectionException(CancelReasonCode.BAD_FRAME_RECEIVED_FOR_THIS_STATE, logId, stream.getStreamId(), t.getMessage(), t));
else if (t instanceof NoTransitionStreamError)
fut.completeExceptionally(new StreamException(CancelReasonCode.CLOSED_STREAM, logId, stream.getStreamId(), t.getMessage(), t));
else
fut.completeExceptionally(t);
return fut;
}
Aggregations