remotelock.java

来自「java版ace,java程序员值得一看」· Java 代码 · 共 544 行 · 第 1/2 页

JAVA
544
字号
package JACE.netsvcs.Token;

import java.io.*;
import JACE.Concurrency.*;
import JACE.ASX.*;
import JACE.Connection.*;
import JACE.OS.*;

/**
 * Proxy used by clients to connect to the token service.  This 
 * implements the AbstractLock interface, so can be used like any
 * other synchronization mechanism.  The user can either use this
 * class directly, or use a proxy which already inputs its type.
 * <P>
 * Currently, a separate instance (and thus a separate socket connection)
 * must be used for each thread which accesses the service.  The token
 * service itself could handle multiple client IDs and token names per
 * connection with the following requirement -- since the service blocks
 * in its operations, a shadow mutex would have to be used in the proxy.
 * <P>
 * It would be best if the user called the close () method after finishing
 * up with a RemoteLock, but that is not absolutely necessary.  The socket
 * will be closed when the JVM exits or finalize is called.  (That will also
 * free the actual token in the token service in case release was never
 * called.)
 * <P>
 * The SLEEPHOOK result is never returned, only SUCCESS or FAILURE.  (C++
 * version doesn't seem to indicate the sleep hook result.)
 *
 *@see MutexHandler
 *@see RWMutexHandler
 *@see JACE.Concurrency.AbstractLock
 *
 *@author Everett Anderson
 */
public class RemoteLock extends SvcHandler implements AbstractLock
{
  /**
   * Accessor for the token name. 
   *
   *@return name of the token
   */
  public String tokenName ()
  {
    return request_.tokenName ();
  }

  /**
   * Set the name of the token.
   */
  public void tokenName (String name)
  {
    request_.tokenName (name);
  }

  /**
   * Accessor for the client ID.
   */
  public String clientID ()
  {
    return request_.clientID ();
  }

  /**
   * Set the client ID.
   */
  public void clientID (String clientID)
  {
    request_.clientID (clientID);
  }

  /**
   * Constructor.
   *
   *@see LockTypes
   *@param tokenType  type of token to create in the token service
   *@param proxyType  type of proxy to define this RemoteLock as
   *@param tokenName  name of the token to connect to in the token service
   *@param clientID   clientID to use to refer to this client
   *@param host       host name of the token service
   *@param port       port to connect to for the token service
   */
  public RemoteLock (int tokenType,
		     int proxyType,
		     String tokenName,
		     String clientID,
		     String host,
		     int port)
  {
    host_ = host;
    port_ = port;

    // Only allocates one reply and one request
    reply_ = new TokenReply ();

    request_ = new TokenRequest (tokenType,
				 proxyType,
				 0,
				 tokenName,
				 clientID);
  }

  /**
   * Reconnect this proxy to the token service. 
   *
   *@exception LockException problem occured in reconnecting
   */
  protected void reconnect () throws LockException
  {
    Connector c = new Connector ();
    c.open (host_, port_);

    try {
      c.connect (this);
    } catch (InstantiationException e) {
      throw new LockException (e.getMessage());
    } catch (IllegalAccessException e) {
      throw new LockException (e.getMessage());
    } catch (IOException e) {
      throw new LockException (e.getMessage());
    }
  }

  /**
   * Check to see if this RemoteLock is connected.
   */
  public boolean connected ()
  {
    return connected_;
  }

  /**
   * Initialize this RemoteLock.  Called by Connector.
   */
  public int open (Object obj)
  {
    connected_ = true;
    return 0;
  }

  /**
   * Shut down the connection to the server.  Current implementation
   * calls close ().
   */
  public int close (long flags)
  {
    return close ();
  }

  /**
   * Shut down the connection to the server and mark this lock
   * as disconnected.
   */
  public int close ()
  {
    if (connected ()) {
      try {
	connected_ = false;
	peer ().close ();
      } catch (IOException e) {
	return -1;
      }
    }
    
    return 0;
  }

  /**
   * Send the given request to the token service, throwing a 
   * LockException on error.
   */
  protected void sendRequest (TokenRequest request) throws LockException
  {
    try {
      if (!connected ())
	reconnect ();

      request.streamOutTo (peer ().dataOutputStream ());

    } catch (IOException e) {
      close ();
      throw new LockException (e.getMessage ());
    }
  }

  /**
   * Receive a reply from the token service, throwing a LockException
   * on error.
   */
  protected void receiveReply (TokenReply reply) throws LockException
  {
    if (!connected ())
      throw new LockException ("Proxy wasn't connected, any replies lost");

    try {

      reply.streamInFrom (peer ().dataInputStream ());

    } catch (IOException e) {
      close ();
      throw new LockException (e.getMessage ());
    }
  }

  /**
   * For errors that shouldn't generate exceptions, return the
   * appropriate result code as defined in AbstractLock.
   *
   *@return AbstractLock.SUCCESS or AbstractLock.FAILURE
   */
  protected int processErrno (TokenReply reply)
  {
    switch (reply.errno ())
      {
      case TokenReply.NO_ERRORS:
	return AbstractLock.SUCCESS;
      case TokenReply.EIO:
	close ();
	return AbstractLock.FAILURE;
      default:
	return AbstractLock.FAILURE;
      }
  }

  /**
   * Make a request to the token service with the given operation
   * type and arguments.
   *
   *@see LockOperations
   *@see LockTypes
   *@param operationType type of operation to perform
   *@param proxyType type of proxy this is
   *@param requeuePosition put this owner at this position in the
   *                       waiting queue (only makes sense if the
   *                       operation is renew)
   *@return AbstractLock.SUCCESS or AbstractLock.FAILURE
   *@exception LockException remote access error occured
   */
  protected int makeRequest (int operationType,
			     int proxyType,
			     int requeuePosition)
    throws LockException
  {
    request_.operationType (operationType);
    request_.proxyType (proxyType);
    request_.requeuePosition (requeuePosition);
    request_.useTimeout (false);

    sendRequest (request_);
    receiveReply (reply_);
    
    // make sure that if someone does send a magic cookie arg back,
    // to keep it going
    request_.arg (reply_.arg ());

    return processErrno (reply_);
  }

  /**
   * Make a request to the token service with the given arguments
   * that must be performed by the given absolute time timeout.
   * Currently, the timeout is managed by the remote service.
   *
   *@see LockOperations
   *@see LockTypes
   *@param operationType type of operation to perform
   *@param proxyType type of proxy this is
   *@param requeuePosition put this owner at this position in the
   *                       waiting queue (only makes sense if the
   *                       operation is renew)
   *@param timeout absolute time timeout to accomplish the operation by
   *@return AbstractLock.SUCCESS or AbstractLock.FAILURE

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?