com.ibm.as400.access.PxClientReadDaemon Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400 Show documentation
Show all versions of jt400 Show documentation
The Open Source version of the IBM Toolbox for Java
The newest version!
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: PxClientReadDaemon.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2000 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
//
// Tunneling -- HTTP is stateless which means there is no persistent
// connection between the client and server. With tunneling, a connection
// is made, data sent and received, then disconnected. This class now
// has two personalities:
// 1) normal proxy -- start a background thread that sits on
// on the connection waiting for data. When
// data arrives, handle it (possible asnychronous processing).
// 2) tunnel proxy -- no additional thread is started. When it is time
// to read data a connection is passed to this class.
//
import java.util.Hashtable;
import java.io.EOFException;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
// @B1D import java.net.SocketException; // @A1A
/**
The PxClientReadDaemon class represents a read daemon for reading
replies from the proxy server.
**/
class PxClientReadDaemon
extends StoppableThread
{
private static final String copyright = "Copyright (C) 1997-2000 International Business Machines Corporation and others.";
// Private data.
private PxDSFactory factory_ = new PxDSFactory();
private InputStream input_;
private InvocationTargetException invocationTargetException_ = null;
private IOException ioException_ = null;
private Hashtable replies_ = new Hashtable();
private boolean running_ = false;
private boolean started_ = false;
// @D1a new c'tor
// Use this c'tor when Tunneling
public PxClientReadDaemon ()
{
super("Proxy client read daemon-" + newId());
// Mark this as a daemon thread so that its running does
// not prevent the JVM from going away.
setDaemon(true);
}
public PxClientReadDaemon (InputStream input)
{
super("Proxy client read daemon-" + newId());
// Mark this as a daemon thread so that its running does
// not prevent the JVM from going away.
setDaemon(true);
input_ = input;
}
public PxDSFactory getFactory()
{
return factory_;
}
// Traditional proxy uses this method.
public PxRepCV getReply(long correlationId)
throws InvocationTargetException, IOException
{
Long key = Long.valueOf(correlationId);
// Loop and poll, until the correct reply has been read by the
// read daemon thread.
while(true) {
// If any relevant exceptions were caught by the read daemon
// thread, then throw them now.
if (ioException_ != null) {
IOException ioEx = ioException_;
ioException_ = null;
throw ioEx;
}
if (invocationTargetException_ != null) {
InvocationTargetException ite = invocationTargetException_;
invocationTargetException_ = null;
throw ite ;
}
// Look in the hashtable to see if the correct reply has been
// read.
synchronized(this) {
if (Trace.isTraceProxyOn()) {
Trace.log(Trace.PROXY, this, "correlationId is "+correlationId);
}
if (replies_.containsKey(key)) {
PxRepCV reply = (PxRepCV)replies_.get(key);
replies_.remove(key);
return reply;
}
// If not found, but the read daemon is still running,
// then wait patiently and efficiently.
if (running_ || !started_) {
try {
wait();
}
catch(InterruptedException e) {
// Ignore.
}
}
// If not found, but the read daemon has stopped, then
// give up hope, something strange has happened.
else {
if (Trace.isTraceErrorOn())
Trace.log(Trace.ERROR, "Proxy read daemon stopped, but replies are expected.");
throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR);
}
}
}
}
public void register(PxDSRV datastream)
{
factory_.register(datastream);
}
// A thread is created only when using traditional proxy.
public void run()
{
started_ = true;
running_ = true;
// @B1D int exceptionCounter = 0; // @A1A
PxRepCV reply;
try {
while (canContinue()) {
ioException_ = null;
if (Trace.isTraceProxyOn())
Trace.log(Trace.PROXY,this,"calling factory_.getNextDS");
reply = (PxRepCV)factory_.getNextDS(input_);
if (Trace.isTraceProxyOn())
reply.dump (Trace.getPrintWriter ());
// @B1D // We had a successful read, reset the exception counter. // @A1A
// @B1D exceptionCounter = 0; // @A1A
// If the correlation id is set, just store the reply
// in the hashtable. This means that somebody is
// waiting for it and they will ask for it when the
// time is right.
long correlationId = reply.getCorrelationId();
if (correlationId >= 0) {
synchronized(this) {
replies_.put(Long.valueOf(correlationId), reply);
notifyAll();
}
}
// Otherwise, process it and forget about it!
else
reply.process();
}
if (Trace.isTraceProxyOn ())
Trace.log(Trace.PROXY, this, "Exited while loop");
}
catch(InvocationTargetException e) {
invocationTargetException_ = e;
}
catch(IOException e) {
// If an exception is thrown AND the thread was stopped safely,
// then ignore the exception, i.e., assume the exception just
// resulted in the socket being closed.
if ((! wasStoppedSafely()) && (!(e instanceof EOFException))) {
ioException_ = e;
if (Trace.isTraceProxyOn ())
Trace.log(Trace.PROXY, "Ending read daemon", e);
}
// No need to throw exception (there is nobody to catch it!)
// Simply, end the thread.
synchronized(this) {
notifyAll();
}
}
if (Trace.isTraceProxyOn()) {
Trace.log(Trace.PROXY, this, "Leaving running loop "
+ "invocationTargetException_="+invocationTargetException_+
" ioException_="+ioException_);
}
running_ = false;
}
// @D1a new method.
// This method is used when tunneling. The CID and stream to read are
// passed each time we retrieve data from the server.
public PxRepCV getReply(long CID, InputStream input_)
throws InvocationTargetException, IOException
{
if (Trace.isTraceProxyOn())
Trace.log(Trace.PROXY, this, "getReply");
// try
// {
Long key = Long.valueOf(CID);
if (replies_.containsKey(key))
{
PxRepCV reply = (PxRepCV)replies_.get(key);
replies_.remove(key);
return reply;
}
while(true)
{
PxRepCV reply;
if (Trace.isTraceProxyOn())
Trace.log(Trace.PROXY,this,"calling factory_.getNextDS");
reply = (PxRepCV)factory_.getNextDS(input_);
if (Trace.isTraceProxyOn())
reply.dump (Trace.getPrintWriter ());
// If the correlation id is set, just store the reply
// in the hashtable. This means that somebody is
// waiting for it and they will ask for it when the
// time is right.
long correlationId = reply.getCorrelationId();
if (correlationId != CID) {
replies_.put(Long.valueOf(correlationId), reply);
}
else
{
reply.process();
return reply;
}
}
// }
// catch(InvocationTargetException e)
// {
// invocationTargetException_ = e;
// }
// catch(IOException e)
// {
// if (Trace.isTraceErrorOn ())
// Trace.log(Trace.ERROR, "Ending read daemon", e);
//
// }
// running_ = false;
// return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy