package org.jcon.df.request;

import org.jcon.util.GenLib;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import java.rmi.RemoteException;

/**
 * A pool worker that performs a Request. By reusing workers
 * we achieve no worker creation per client request. This
 * improves performance.
 *
 * @author Jack Harich
 */
public class Performer extends UnicastRemoteObject
    implements PerformerRemote,
    Unreferenced  {

//---------- Private Fields ------------------------------
private PerformerPool   performerPool;
private RequestServices services;

private static final boolean DEBUG = false;

//---------- Initialization ------------------------------
public Performer() throws RemoteException {
    super();
}
//---------- PerformerRemote Implementation --------------
/**
 * The client calls this method to perform the all-important
 * Request. This is the crucial client/server call. The
 * Request will be returned for use by the client.
 */
public synchronized Object performRequest(Request request)
        throws RemoteException {

    try {
        // DUPECODE with Database.performRequest()
        // and DatabaseServer
        // Configure request
        request.clearFailureData();
        request.setRequestServices(services);

        // Perform request
if (DEBUG) print(".performRequest() - before prepareResources()" +
" - Current thread = " + Thread.currentThread());

        services.prepareResources(request);

        // Transaction
        String okay = services.validateRequest(request);
        if (okay != null) {
            request.setFailureText(okay);
        } else {
if (DEBUG) print(".performRequest() - before perform()");
            request.perform();
        }
        return request; // Cast by client to Request type

    } catch(Exception ex) {
        GenLib.exception("Performer.performRequest()",
            "Large problem here. Aborting method.", ex);
        request.setFailureText("Failure in Performer.performRequest()");
        request.setFailureException(ex);
        return null;
    } finally {
if (DEBUG) print(".performRequest() - before releaseResources()");
        services.releaseResources();
    }
}
/**
 * Called by the client to release the performer, allowing
 * it to be returned to the pool. Clients should call this
 * method when the performer is dereferenced. This
 * technique is faster than remote GC Unreferenced use.
 */
public synchronized void release() throws RemoteException {
    performerPool.checkIn(this, false);
}
//---------- Unreferenced Implementation -----------------
// "Called when there are no current references to this remote object."
// 3/38/97 - Clocked a 20 minute wait before this was called
public void unreferenced() {
    System.out.println("Performer.unreferenced() called");
    performerPool.checkIn(this, true);
}
//---------- Properties ----------------------------------
// Properties not synchronized since done before running
public void setPerformerPool(PerformerPool performerPool) {
    this.performerPool = performerPool;
}
public void setRequestServices(RequestServices requestServices) {
    services = requestServices;
}
//---------- Public Methods ------------------------------
/**
 * Starts the performer. Currrently this does nothing and
 * is for future initialization. Call this method
 * after setting necessary properties.
 */
public synchronized void start() {
    // Do nothing
}
/**
 * Stops the performer. Currently this does nothing and is
 * for future use.
 */
public synchronized void stop() {
    // Do nothing
}
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("Performer" + text);
}

} // End class
