Package org.apache.geronimo.corba.channel

Source Code of org.apache.geronimo.corba.channel.SocketTransportBase

/**
*
* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
*
*  Licensed 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.geronimo.corba.channel;

import java.io.IOException;
import java.net.Socket;

import EDU.oswego.cs.dl.util.concurrent.Mutex;
import EDU.oswego.cs.dl.util.concurrent.Semaphore;
import EDU.oswego.cs.dl.util.concurrent.Sync;

import org.apache.geronimo.corba.channel.nio.ParticipationExecutor;

public abstract class SocketTransportBase extends Transport {

  static protected final int RCV_BUFFER_SIZE = getIntProperty(
      "org.freeorb.rcv_buffer_size", 64 * 1024);

  static protected final int SND_BUFFER_SIZE = getIntProperty(
      "org.freeorb.snd_buffer_size", 64 * 1024);

  protected InputHandler handler;

  protected Thread inputWorker;

  protected Sync inputWorkerLock = new Mutex();

  protected RingByteBuffer receiveBuffer;

  protected RingByteBuffer sendBuffer;

  protected Semaphore outputWorkerLock = new Semaphore(1);

  protected Thread outputWorker;

  protected TransportManager manager;

  private ParticipationExecutor executor;

  protected Socket sock;

  protected SocketTransportBase(TransportManager manager,
      InputHandler handler, Socket sock) {
    this.manager = manager;
    this.handler = handler;
    this.executor = new ParticipationExecutor(manager.getExecutor());
    this.sock = sock;

    this.receiveBuffer = allocateReceiveBuffer(RCV_BUFFER_SIZE);
    this.sendBuffer = allocateSendBuffer(SND_BUFFER_SIZE);
  }

  protected abstract RingByteBuffer allocateSendBuffer(int bufferSize);

  protected abstract RingByteBuffer allocateReceiveBuffer(int bufferSize);

  private static int getIntProperty(String string, int defaultValue) {
    try {
      return Integer.parseInt(System.getProperty(string, ""));
    } catch (NumberFormatException ex) {
      return defaultValue;
    }
  }

  public void releaseOutputChannel() {
    if (outputWorker == Thread.currentThread()) {

      try {
        sendBuffer.flush();
      } catch (IOException e) {
        e.printStackTrace();
      }

      outputWorker = null;
      outputWorkerLock.release();
    }
  }

  /**
   * wait for the output channel to become available
   */
  public OutputChannel getOutputChannel() {

    do {
      try {
        outputWorkerLock.acquire();
      } catch (InterruptedException e) {
        continue;
      }
    } while (false);

    assertEquals(outputWorker, null);

    outputWorker = Thread.currentThread();
    return sendBuffer.getOutputChannel();
  }

  public InputChannel getInputChannel() {
    LOOP: do {
      try {
        inputWorkerLock.acquire();
      } catch (InterruptedException e) {
        continue LOOP;
      }
    } while (false);

    try {

      if (inputWorker == null) {
        inputWorker = Thread.currentThread();

      } else if (inputWorker != Thread.currentThread()) {
        throw new IllegalStateException(
            "only the designated input worker can do that");
      }

    } finally {
      inputWorkerLock.release();
    }

    return receiveBuffer.getInputChannel();
  }

  /**
   * this runnable is started when input is available
   */
  protected final Runnable processInput = new Runnable() {
    public void run() {

      assertEquals(inputWorker, null);

      inputWorker = Thread.currentThread();
      try {
        inputWorkerLock.release();
        handler.inputAvailable(SocketTransportBase.this);
      } catch (Error e) {
        e.printStackTrace();
      } catch (RuntimeException e) {
        e.printStackTrace();
      } finally {
        releaseOutputChannel();
        unsetInputWorker();
      }
    }
  };

  /**
   * to be called when something is added to the input buffer
   */
  protected void processAvailableInput() throws InterruptedException {
    inputWorkerLock.acquire();

    // is there someone processing input?
    // if not, then we need to start a new
    // input processor

    if (inputWorker == null && !receiveBuffer.isEmpty() && handler != null) {
      executor.execute(processInput);
    } else {
      inputWorkerLock.release();
    }
  }

  public void releaseInputChannel() {
    unsetInputWorker();
  }

  void unsetInputWorker() {

    Thread.interrupted();

    do {
      try {
        inputWorkerLock.acquire();
      } catch (InterruptedException e) {
        continue;
      }
    } while (false);

    if (inputWorker == Thread.currentThread()) {
      inputWorker = null;
      if (!receiveBuffer.isEmpty() && handler != null) {
        // we're done with this request, but there
        // is a new request (partially) available

        do {
          try {
            executor.execute(processInput);
          } catch (InterruptedException e) {
            continue;
          }
        } while (false);
      } else {
        // we're done with this request and there is
        // no more input
        inputWorkerLock.release();
      }
    } else {
      // response was given to another thread via signalResponse
      inputWorkerLock.release();
    }

  }

  public void registerResponse(Object key) {
    executor.create(key);
  }

  public Object waitForResponse(Object key) {

    do {
      try {
        inputWorkerLock.acquire();
      } catch (InterruptedException e) {
        continue;
      }
    } while (false);

    if (inputWorker == Thread.currentThread()) {
      inputWorker = null;
    }
    inputWorkerLock.release();

    Object value = null;
    try {
      value = executor.participate(key);
    } catch (InterruptedException e) {
      // TODO: dont ignore
    }

    inputWorker = Thread.currentThread();
    inputWorkerLock.release(); // {22}

    return value;
  }

  public void signalResponse(Object key, Object value) {
    assertEquals(inputWorker, Thread.currentThread());

    // this lock is released at {22}, when the
    // relevant participant reaquires control
    do {
      try {
        inputWorkerLock.acquire();
      } catch (InterruptedException e) {
        continue;
      }
    } while (false);

    inputWorker = null;
    executor.release(key, value);
  }

  public void setInputHandler(InputHandler handler) {
    this.handler = handler;
  }

  private void assertEquals(Object o1, Object o2) {
    if (o1 != o2) {
      throw new IllegalStateException("assertion failed");
    }
  }

  public void close() throws IOException {
    sock.close();
  }

}
TOP

Related Classes of org.apache.geronimo.corba.channel.SocketTransportBase

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.