home | career | drupal | java | mac | mysql | perl | scala | uml | unix  

ActiveMQ example source code file (CommandDatagramSocket.java)

This example ActiveMQ source code file (CommandDatagramSocket.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - ActiveMQ tags/keywords

bytearrayoutputstream, bytearrayoutputstream, channel, command, commanddatagramsocket, datagrampacket, datagrampacket, datainputstream, dataoutputstream, io, ioexception, ioexception, net, network, object, object, socketaddress

The ActiveMQ CommandDatagramSocket.java source code

/**
 * 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.activemq.transport.udp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;

import org.apache.activemq.command.Command;
import org.apache.activemq.command.Endpoint;
import org.apache.activemq.command.LastPartialCommand;
import org.apache.activemq.command.PartialCommand;
import org.apache.activemq.openwire.BooleanStream;
import org.apache.activemq.openwire.OpenWireFormat;
import org.apache.activemq.transport.reliable.ReplayBuffer;
import org.apache.activemq.util.ByteArrayInputStream;
import org.apache.activemq.util.ByteArrayOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A strategy for reading datagrams and de-fragmenting them together.
 * 
 * 
 */
public class CommandDatagramSocket extends CommandChannelSupport {

    private static final Logger LOG = LoggerFactory.getLogger(CommandDatagramSocket.class);

    private DatagramSocket channel;
    private Object readLock = new Object();
    private Object writeLock = new Object();

    private volatile int receiveCounter;

    public CommandDatagramSocket(UdpTransport transport, OpenWireFormat wireFormat, int datagramSize, SocketAddress targetAddress, DatagramHeaderMarshaller headerMarshaller,
                                 DatagramSocket channel) {
        super(transport, wireFormat, datagramSize, targetAddress, headerMarshaller);
        this.channel = channel;
    }

    public void start() throws Exception {
    }

    public void stop() throws Exception {
    }

    public Command read() throws IOException {
        Command answer = null;
        Endpoint from = null;
        synchronized (readLock) {
            while (true) {
                DatagramPacket datagram = createDatagramPacket();
                channel.receive(datagram);

                // TODO could use a DataInput implementation that talks direct
                // to the byte[] to avoid object allocation
                receiveCounter++;
                DataInputStream dataIn = new DataInputStream(new ByteArrayInputStream(datagram.getData(), 0, datagram.getLength()));
                
                from = headerMarshaller.createEndpoint(datagram, dataIn);
                answer = (Command)wireFormat.unmarshal(dataIn);
                break;
            }
        }
        if (answer != null) {
            answer.setFrom(from);

            if (LOG.isDebugEnabled()) {
                LOG.debug("Channel: " + name + " about to process: " + answer);
            }
        }
        return answer;
    }

    public void write(Command command, SocketAddress address) throws IOException {
        synchronized (writeLock) {

            ByteArrayOutputStream writeBuffer = createByteArrayOutputStream();
            DataOutputStream dataOut = new DataOutputStream(writeBuffer);
            headerMarshaller.writeHeader(command, dataOut);

            int offset = writeBuffer.size();

            wireFormat.marshal(command, dataOut);

            if (remaining(writeBuffer) >= 0) {
                sendWriteBuffer(address, writeBuffer, command.getCommandId());
            } else {
                // lets split the command up into chunks
                byte[] data = writeBuffer.toByteArray();
                boolean lastFragment = false;
                int length = data.length;
                for (int fragment = 0; !lastFragment; fragment++) {
                    writeBuffer = createByteArrayOutputStream();
                    headerMarshaller.writeHeader(command, dataOut);

                    int chunkSize = remaining(writeBuffer);

                    // we need to remove the amount of overhead to write the
                    // partial command

                    // lets write the flags in there
                    BooleanStream bs = null;
                    if (wireFormat.isTightEncodingEnabled()) {
                        bs = new BooleanStream();
                        bs.writeBoolean(true); // the partial data byte[] is
                        // never null
                    }

                    // lets remove the header of the partial command
                    // which is the byte for the type and an int for the size of
                    // the byte[]

                    // data type + the command ID + size of the partial data
                    chunkSize -= 1 + 4 + 4;

                    // the boolean flags
                    if (bs != null) {
                        chunkSize -= bs.marshalledSize();
                    } else {
                        chunkSize -= 1;
                    }

                    if (!wireFormat.isSizePrefixDisabled()) {
                        // lets write the size of the command buffer
                        dataOut.writeInt(chunkSize);
                        chunkSize -= 4;
                    }

                    lastFragment = offset + chunkSize >= length;
                    if (chunkSize + offset > length) {
                        chunkSize = length - offset;
                    }

                    if (lastFragment) {
                        dataOut.write(LastPartialCommand.DATA_STRUCTURE_TYPE);
                    } else {
                        dataOut.write(PartialCommand.DATA_STRUCTURE_TYPE);
                    }

                    if (bs != null) {
                        bs.marshal(dataOut);
                    }

                    int commandId = command.getCommandId();
                    if (fragment > 0) {
                        commandId = sequenceGenerator.getNextSequenceId();
                    }
                    dataOut.writeInt(commandId);
                    if (bs == null) {
                        dataOut.write((byte)1);
                    }

                    // size of byte array
                    dataOut.writeInt(chunkSize);

                    // now the data
                    dataOut.write(data, offset, chunkSize);

                    offset += chunkSize;
                    sendWriteBuffer(address, writeBuffer, commandId);
                }
            }
        }
    }

    public int getDatagramSize() {
        return datagramSize;
    }

    public void setDatagramSize(int datagramSize) {
        this.datagramSize = datagramSize;
    }

    // Implementation methods
    // -------------------------------------------------------------------------
    protected void sendWriteBuffer(SocketAddress address, ByteArrayOutputStream writeBuffer, int commandId) throws IOException {
        byte[] data = writeBuffer.toByteArray();
        sendWriteBuffer(commandId, address, data, false);
    }

    protected void sendWriteBuffer(int commandId, SocketAddress address, byte[] data, boolean redelivery) throws IOException {
        // lets put the datagram into the replay buffer first to prevent timing
        // issues
        ReplayBuffer bufferCache = getReplayBuffer();
        if (bufferCache != null && !redelivery) {
            bufferCache.addBuffer(commandId, data);
        }

        if (LOG.isDebugEnabled()) {
            String text = redelivery ? "REDELIVERING" : "sending";
            LOG.debug("Channel: " + name + " " + text + " datagram: " + commandId + " to: " + address);
        }
        DatagramPacket packet = new DatagramPacket(data, 0, data.length, address);
        channel.send(packet);
    }

    public void sendBuffer(int commandId, Object buffer) throws IOException {
        if (buffer != null) {
            byte[] data = (byte[])buffer;
            sendWriteBuffer(commandId, replayAddress, data, true);
        } else {
            if (LOG.isWarnEnabled()) {
                LOG.warn("Request for buffer: " + commandId + " is no longer present");
            }
        }
    }

    protected DatagramPacket createDatagramPacket() {
        return new DatagramPacket(new byte[datagramSize], datagramSize);
    }

    protected int remaining(ByteArrayOutputStream buffer) {
        return datagramSize - buffer.size();
    }

    protected ByteArrayOutputStream createByteArrayOutputStream() {
        return new ByteArrayOutputStream(datagramSize);
    }

    public int getReceiveCounter() {
        return receiveCounter;
    }
}

Other ActiveMQ examples (source code examples)

Here is a short list of links related to this ActiveMQ CommandDatagramSocket.java source code file:

new blog posts

 

Copyright 1998-2016 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.