Package com.trendrr.strest.server.connections

Source Code of com.trendrr.strest.server.connections.StrestConnectionGroup

/**
*
*/
package com.trendrr.strest.server.connections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;

import com.trendrr.strest.StrestUtil;
import com.trendrr.strest.server.ResponseBuilder;
import com.trendrr.strest.server.StrestResponseEncoder;
import com.trendrr.strest.server.callbacks.ConnectionGroupEmptyCallback;
import com.trendrr.strest.server.callbacks.DisconnectCallback;
import com.trendrr.strest.server.callbacks.TxnCompleteCallback;


/**
*
* Allows us to write identical requests to multiple connections, using
* the connections individual transactions.
*
* Connections are automatically removed when they are disconnected.
*
* @author Dustin Norlander
* @created Mar 16, 2011
*
*/
public class StrestConnectionGroup implements TxnCompleteCallback {

  protected Log log = LogFactory.getLog(StrestConnectionGroup.class);

  private int size = 0; //we keep our own copy of size as the connections.size is slow
  private ConcurrentSkipListSet<StrestConnectionTxn> connections = new ConcurrentSkipListSet<StrestConnectionTxn>();

  private ConcurrentLinkedQueue<ConnectionGroupEmptyCallback> emptyCallbacks = new ConcurrentLinkedQueue<ConnectionGroupEmptyCallback>();
 
  private AtomicBoolean closed = new AtomicBoolean(false);
 
  /**
   * Adds a new connection to the group.
   * @param connection
   * @param txnId
   */
  public synchronized void addConnection(StrestConnectionTxn connection) {
    if (closed.get()) {
      //TODO: probably should throw an exception
      log.warn("This connection group is closed! ");
      return;
    }
   
    if (!connections.add(connection)) {
      log.warn("Connection already present in the group!: " + connection);
      return;
    }
    size++;
    connection.onTxnComplete(this);
  }
 
  public boolean removeConnection(StrestConnectionTxn connection) {
    try {
      if (connections.remove(connection)){
        size--;
        return true;
      }
    } finally {
      this.onEmptyCallback();
    }
    return false;
  }
 
  private void onEmptyCallback() {
    if (this.isEmpty()) {
      ConnectionGroupEmptyCallback cb = emptyCallbacks.poll();
      while(cb != null) {
        cb.connectionGroupEmpty(this);
        cb = emptyCallbacks.poll();
      }
    }
  }
 
  /**
   * register a callback for when this connection group is empty.
   *
   * Note this will never be called if this group never has any members.
   *
   * @param callback
   */
  public void onEmpty(ConnectionGroupEmptyCallback callback) {
    this.emptyCallbacks.add(callback);
  }
 
 
  /* (non-Javadoc)
   * @see com.trendrr.strest.server.callbacks.TxnCompleteCallback#txnComplete(com.trendrr.strest.server.connections.StrestConnectionTxn)
   */
  @Override
  public void txnComplete(StrestConnectionTxn connection) {
    this.removeConnection(connection);
  }
 
 
  /**
   * sends a message to all the connections + txn in the group.
   * @param response
   * @return
   */
  public Collection<ChannelFuture> sendMessage(HttpResponse response) {
    Collection<ChannelFuture> futures = new ArrayList<ChannelFuture>();
    for (StrestConnectionTxn con : this.connections) {
      HttpResponse res = StrestResponseEncoder.copyHeaders(response);
     
      //We don't allow any content encoding.
      //TODO: we should sort the gzip accept ones vs the ungzipped.
      res.setHeader(HttpHeaders.Names.CONTENT_ENCODING, "identity");
      res.setContent(response.getContent()); //all share the same content buffer.
      futures.add(con.sendMessage(res));
    }
    return futures;
  }
 
  public Collection<ChannelFuture> sendMessage(ResponseBuilder response) {
    return this.sendMessage(response.getResponse());
  }
 
  public int size() {
    return size;
  }
 
  public boolean isEmpty() {
    return this.connections.isEmpty();
  }
 
  public boolean contains(StrestConnectionChannel connection) {
    return this.connections.contains(connection);
  }
 
  /**
   * closes this connection group and ends the transaction for *all* participants
   */
  public void close() {
    this.closed.set(true);
    StrestConnectionTxn con = this.connections.pollFirst();
    while (con != null) {
      con.close();
      con = this.connections.pollFirst();
    }
  }
}
TOP

Related Classes of com.trendrr.strest.server.connections.StrestConnectionGroup

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.