
org.simpleframework.transport.SegmentBuilder Maven / Gradle / Ivy
/*
* SegmentBuilder.java February 2008
*
* Copyright (C) 2008, Niall Gallagher
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
package org.simpleframework.transport;
import java.io.IOException;
import java.util.LinkedList;
/**
* The SegmentBuilder
object is used to build segments
* such that they are of a sufficient size to deliver in a write.
* This basically ensures that each packet is of a sufficiently
* large size, if not then it transfers bytes from packets higher
* up the queue to ones lower down, ensuring a minimum packet size.
*
* @author Niall Gallagher
*
* @see org.simpleframework.transport.Writer
*/
class SegmentBuilder {
/**
* This is the packet queue that is used to queue packets.
*/
private final Queue queue;
/**
* Constructor for the SegmentBuilder
object. This
* is used to create a queue of packets such that each packet is
* of a minimum size. To ensure packets are of a minimum size
* this aggregates them by moving bytes between packets.
*/
public SegmentBuilder() {
this(1024);
}
/**
* Constructor for the SegmentBuilder
object. This
* is used to create a queue of packets such that each packet is
* of a minimum size. To ensure packets are of a minimum size
* this aggregates them by moving bytes between packets.
*
* @param size this is the size to aggregate each packet to
*/
public SegmentBuilder(int size) {
this.queue = new Queue();
}
/**
* This will aggregate the queued packets in to a packet that is
* at least the minimum required size. If there are none in the
* queue then this will return null. Also if the queued packets
* are of zero length this will return null.
*
* @return this returns a packet from the queue of packets
*/
public Segment build() throws IOException {
Packet packet = queue.peek();
if(packet == null) {
return null;
}
return create(packet);
}
/**
* This will aggregate the queued packets in to a packet that is
* at least the minimum required size. If there are none in the
* queue then this will return null. Also if the queued packets
* are of zero length this will return null.
*
* @packet this is the packet to wrap within a closer packet
*
* @return this returns a packet from the queue of packets
*/
private Segment create(Packet packet) throws IOException {
int length = packet.length();
if(length <= 0) {
packet.close();
queue.poll();
return build();
}
return new Segment(packet, queue);
}
/**
* This will aggregate the queued packets in to a packet that is
* at least the minimum required size. If there are none in the
* queue then this will return null. Also if the queued packets
* are of zero length this will return null.
*
* @packet this is a new packet to be added to the packet queue
*
* @return this returns a packet from the queue of packets
*/
public Segment build(Packet packet) throws IOException {
boolean update = queue.offer(packet);
long sequence = packet.sequence();
if(!update) {
throw new PacketException("Could not aggregate packet " + sequence);
}
return build();
}
/**
* This returns the total length of all packets within the queue.
* This can be used to determine if any packets can be created
* using the aggregate
method. If the length is zero
* there are no packets waiting to be aggregated.
*
* @return this returns the total length of all queued packets
*/
public int length() throws IOException{
int count = 0;
for(Packet packet : queue) {
count += packet.length();
}
return count;
}
/**
* This is used to close all packets within the builder. This
* is done when there is an error or the client has closed the
* connection from their size. This is important as it releases
* any resources occupied by the queued packets.
*/
public void close() throws IOException {
for(Packet packet : queue) {
packet.close();
}
queue.clear();
}
/**
* The Queue
object is used to create a queue of
* packets that represent the order the packets have been added
* to the builder. This order ensures that the packets can
* be reassembled on the client size as a complete resource.
*
* @author Niall Gallagher
*/
private class Queue extends LinkedList {
/**
* Constructor for the SegmentBuilder
object. This
* is used to create a queue to order the packets that are
* to be aggregated and delivered to a client.
*/
public Queue() {
super();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy