Package com.dianping.cat.message.io

Source Code of com.dianping.cat.message.io.TcpSocketSender

package com.dianping.cat.message.io;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelFuture;
import org.unidal.helper.Threads;
import org.unidal.helper.Threads.Task;
import org.unidal.lookup.annotation.Inject;

import com.dianping.cat.configuration.ClientConfigManager;
import com.dianping.cat.message.spi.MessageCodec;
import com.dianping.cat.message.spi.MessageQueue;
import com.dianping.cat.message.spi.MessageStatistics;
import com.dianping.cat.message.spi.MessageTree;

public class TcpSocketSender implements Task, MessageSender, LogEnabled {
  public static final String ID = "tcp-socket-sender";

  public static final int SIZE = 10000;

  @Inject
  private MessageCodec m_codec;

  @Inject
  private MessageStatistics m_statistics;

  @Inject
  private ClientConfigManager m_configManager;

  private MessageQueue m_queue = new DefaultMessageQueue(SIZE);

  private List<InetSocketAddress> m_serverAddresses;

  private ChannelManager m_manager;

  private Logger m_logger;

  private transient boolean m_active;

  private AtomicInteger m_errors = new AtomicInteger();

  private AtomicInteger m_attempts = new AtomicInteger();

  private boolean checkWritable(ChannelFuture future) {
    boolean isWriteable = false;

    if (future != null && future.getChannel().isOpen()) {
      if (future.getChannel().isWritable()) {
        isWriteable = true;
      } else {
        int count = m_attempts.incrementAndGet();

        if (count % 1000 == 0 || count == 1) {
          m_logger.error("Netty write buffer is full! Attempts: " + count);
        }
      }
    }

    return isWriteable;
  }

  @Override
  public void enableLogging(Logger logger) {
    m_logger = logger;
  }

  @Override
  public String getName() {
    return "TcpSocketSender";
  }

  @Override
  public void initialize() {
    m_manager = new ChannelManager(m_logger, m_serverAddresses, m_queue, m_configManager);

    Threads.forGroup("cat").start(this);
    Threads.forGroup("cat").start(m_manager);
  }

  @Override
  public void run() {
    m_active = true;

    while (m_active) {
      ChannelFuture future = m_manager.getChannel();

      if (checkWritable(future)) {
        try {
          MessageTree tree = m_queue.poll();

          if (tree != null) {
            sendInternal(tree);
            tree.setMessage(null);
          }

        } catch (Throwable t) {
          m_logger.error("Error when sending message over TCP socket!", t);
        }
      } else {
        try {
          Thread.sleep(5);
        } catch (Exception e) {
          // ignore it
          m_active = false;
        }
      }
    }
  }

  @Override
  public void send(MessageTree tree) {
    boolean result = m_queue.offer(tree);

    if (!result) {
      if (m_statistics != null) {
        m_statistics.onOverflowed(tree);
      }

      int count = m_errors.incrementAndGet();

      if (count % 1000 == 0 || count == 1) {
        m_logger.error("Message queue is full in tcp socket sender! Count: " + count);
      }
    }
  }

  private void sendInternal(MessageTree tree) {
    ChannelFuture future = m_manager.getChannel();
    ChannelBuffer buf = ChannelBuffers.dynamicBuffer(10 * 1024); // 10K

    m_codec.encode(tree, buf);

    int size = buf.readableBytes();

    future.getChannel().write(buf);

    if (m_statistics != null) {
      m_statistics.onBytes(size);
    }
  }

  public void setCodec(MessageCodec codec) {
    m_codec = codec;
  }

  public void setServerAddresses(List<InetSocketAddress> serverAddresses) {
    m_serverAddresses = serverAddresses;
  }

  @Override
  public void shutdown() {
    m_active = false;
    m_manager.shutdown();
  }

}
TOP

Related Classes of com.dianping.cat.message.io.TcpSocketSender

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.