/*
CARNEGIE MELLON UNIVERSITY
NON-EXCLUSIVE END-USER
SOFTWARE LICENSE AGREEMENT
RETSINA(tm)
Reusable Environment for Task Structured Intelligent Network Agents(tm)
IMPORTANT: PLEASE READ THIS SOFTWARE LICENSE AGREEMENT ("AGREEMENT") CAREFULLY.
LICENSE
The CMU Software, together with any fonts accompanying this Agreement, whether
on disk, in read only memory or any other media or in any other form
(collectively, the "CMU Software") is never sold. It is non-exclusively
licensed by Carnegie Mellon University ("CMU") to you solely for your own
internal, non-commercial research purposes on the terms of this Agreement. CMU
retains the ownership of the CMU Software and any subsequent copies of the CMU
Software. The CMU Software and any copies made under this Agreement are subject
to this Agreement.
YOU MAY:
1. LOAD and USE the CMU Software as long as the CMU Software is only
used on one (1) computer by one (1) user at a time. This license does
not allow the CMU Software to exist on more than one (1) computer at
a time or on a computer network, including without limitation an
intranet network or a local area network.
2. USE the CMU Software solely for your own internal, non-commercial
research purposes.
3. COPY the CMU Software for back-up purposes only. You may make one
(1) copy of the CMU Software in machine-readable form for back-up
purposes. The back-up copy must contain all copyright notices
contained in the original CMU Software.
4. TERMINATE this Agreement by destroying the original and all copies
of the CMU Software in whatever form.
YOU MAY NOT:
1. Assign, delegate or otherwise transfer the CMU Software, the
license (including this Agreement), or any rights or obligations
hereunder or thereunder, to another person or entity. Any purported
assignment, delegation or transfer in violation of this provision
shall be void.
2. Loan, distribute, rent, lease, give, sublicense or otherwise
transfer the CMU Software (or any copy of the CMU Software), in whole
or in part, to any other person or entity.
3. Copy, alter, translate, decompile, disassemble, reverse engineer
or create derivative works from the CMU Software, including but not
limited to, modifying the CMU Software to make it operate on non-
compatible hardware.
4. Remove, alter or cause not to be displayed, any copyright notices
or startup messages contained in the CMU Software.
5. Export the CMU Software or the product components in violation of
any United States export laws.
Title to the CMU Software, including the ownership of all copyrights, patents,
trademarks and all other intellectual property rights subsisting in the
foregoing, and all adaptations to and modifications of the foregoing shall at
all times remain with CMU. CMU retains all rights not expressly licensed under
this Agreement. The CMU Software, including any images, graphics, photographs,
animation, video, audio, music and text incorporated therein is owned by CMU or
its suppliers and is protected by United States copyright laws and
international treaty provisions. Except as otherwise expressly provided in
this Agreement, the copying, reproduction, distribution or preparation of
derivative works of the CMU Software is strictly prohibited by such laws and
treaty provisions. Nothing in this Agreement constitutes a waiver of CMU's
rights under United States copyright law.
This Agreement and your rights are governed by the laws of the Commonwealth of
Pennsylvania. If for any reason a court of competent jurisdiction finds any
provision of this Agreement, or portion thereof, to be unenforceable, the
remainder of this Agreement shall continue in full force and effect.
THIS LICENSE SHALL TERMINATE AUTOMATICALLY if you fail to comply with the terms
of this Agreement.
DISCLAIMER OF WARRANTY ON CMU SOFTWARE
You expressly acknowledge and agree that your use of the CMU Software is at
your sole risk.
THE CMU SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, AND CMU
EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY RIGHTS. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE CMU SOFTWARE IS BORNE BY YOU. THIS DISCLAIMER
OF WARRANTIES, REMEDIES AND LIABILITY ARE FUNDAMENTAL ELEMENTS OF THE BASIS OF
THE AGREEMENT BETWEEN CMU AND YOU. CMU WOULD NOT BE ABLE TO PROVIDE THE CMU
SOFTWARE WITHOUT SUCH LIMITATIONS.
LIMITATION OF LIABILITY
THE CMU SOFTWARE IS BEING PROVIDED TO YOU FREE OF CHARGE. UNDER NO
CIRCUMSTANCES, INCLUDING NEGLIGENCE, SHALL CMU BE LIABLE UNDER ANY THEORY OR
FOR ANY DAMAGES INCLUDING, WITHOUT LIMITATION, DIRECT, INDIRECT, GENERAL,
SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR OTHER DAMAGES) ARISING OUT OF
THE USE OF OR INABILITY TO USE THE CMU SOFTWARE OR OTHERWISE RELATING TO THIS
AGREEMENT (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION OR ANY OTHER PECUNIARY
LOSS), EVEN IF CMU HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME
JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
CONSEQUENTIAL DAMAGES SO THIS LIMITATION MAY NOT APPLY TO YOU.
ADDITIONAL PROVISIONS YOU SHOULD BE AWARE OF
This Agreement constitutes the entire agreement between you and CMU regarding
the CMU Software and supersedes any prior representations, understandings and
agreements, either oral or written. No amendment to or modification of this
Agreement will be binding unless in writing and signed by CMU.
U.S. GOVERNMENT RESTRICTED RIGHTS
If the CMU Software or any accompanying documentation is used or acquired by or
on behalf of any unit, division or agency of the United States Government, this
provision applies. The CMU Software and any accompanying documentation is
provided with RESTRICTED RIGHTS. The use, modification, reproduction, release,
display, duplication or disclosure thereof by or on behalf of any unit,
division or agency of the Government is subject to the restrictions set forth
in subdivision (c)(1) of the Commercial Computer Software-Restricted Rights
clause at 48 CFR 52.227-19 and the restrictions set forth in the Rights in
Technical Data-Non-Commercial Items clause set forth in 48 CFR
252.227-7013. The contractor/manufacturer of the CMU Software and accompanying
documentation is Carnegie Mellon University, 5000 Forbes Avenue, Pittsburgh,
Pennsylvania 15213, U.S.A.
*/
/* Copyright (c) 1998, Dirk Kalp, Katia Sycara, RETSINA Project,
Carnegie Mellon University
All rights reserved
*/
/*----------------------------------------------------------------------------
HISTORY:
Spring/Summer 1998 Dirk Kalp (kalp@cs.cmu.edu)
Created the module.
Dec 03 1998 Dirk Kalp (kalp@cs.cmu.edu)
Added this HISTORY log.
----------------------------------------------------------------------------*/
package EDU.cmu.softagents.retsina.Communicator;
import EDU.cmu.softagents.util.*;
import java.util.*;
/** The DispatchOutputMsgs class takes care of the central queue,
dispatchQueue, where msgs to be sent to other agents are
deposited. These queued msgs must be InternalMsgs since they must
contain the necessary internal fields that identify the Connection
on which the msg should be sent. DispatchOutputMsgs also has a
method that allows the central dispatch queue to be bypassed, allowing
callers to directly send a msg on the Connection and block while the
actual socket IO occurs. This interface allows callers to factor in
the IO time and to immediately know if the msg send succeeded. With
the msgs in the dispatch queue, an IO error on the Connection in sending
a msg will not be discovered by the caller until/unless he attempts
to send another msg out on that same Connection. For many callers
(especially those sending responses to client requests), this is an
acceptable mode since, with respect to our open world model, clients
are responsible for dealing with uncertainty and timeouts.
The thread here is in a loop in which it removes a msg from the queue,
looks up its Connection, and uses the Connection to send the msg. This
thread also implements the logging facility for logging msgs sent to
logs such as the demodisplay.
NOTE: For now we will not implement the general logging facility.
Only the demodisplay will be supported. The general mechanism
will have to wait till later. -dirk 4/4/98
NOTE: We have now implemented the general logging facility. -dirk 8/3/98
*/
public class DispatchOutputMsgs extends Thread {
public static /*final*/ boolean DEBUG = true;
protected static int dispatchCount = 0;
private String agentName;
private GenericQueue dispatchQueue;
private MsgLogInterface logFacilityList[];
private Hashtable logFacilityHash;
public DispatchOutputMsgs(String agentName,
GenericQueue dispatchQueue,
MsgLogInterface logFacilityList[],
Hashtable logFacilityHash)
{
this.agentName = agentName;
this.dispatchQueue = dispatchQueue;
this.logFacilityList = logFacilityList;
this.logFacilityHash = logFacilityHash;
this.start();
}
private void sendMessage(InternalMsg iMsg)
{
if (DEBUG)
System.out.println("DispatchOutputMsgs.sendMessage: Sending msg " +
dispatchCount + ": " + iMsg.toString());
String connectionName = iMsg.getField(InternalMsg.CONNECTION_NAME);
// Connection name should not be null since the InternalMsg should
// have been validated before being queued but let's just check
// anyway. If null, we can only print an error msg and return.
if (connectionName == null) {
System.out.println("DispatchOutputMsgs.sendMessage: Connection name " +
"missing from outgoing msg " + dispatchCount +
": " + iMsg.toString());
return;
}
// For Connections that have been flagged with errors, the
// Connection may or may not be in the table. A Connection to
// a client gets removed once a send error occurs on it but a
// Connection to a server should remain until the last descriptor
// for the Connection gets closed. If the Connection is no longer
// present, we just print an error msg and return.
Connection conn =
Communicator.connectionTable.lookupConnection(connectionName);
if (conn == null) {
System.out.println("DispatchOutputMsgs.sendMessage: Lookup of " +
"Connection " + connectionName + " failed for " +
"outgoing msg " + dispatchCount +
": " + iMsg.toString());
return;
}
// Convert the InternalMsg to an ExternalMsg before it goes
// out on the socket.
ExternalMsg eMsg = iMsg.convertToExternal();
// The Connection method will check to see if the Connection is OK.
boolean success = conn.sendMsg(eMsg.toString());
// The Connection needs to know that a msg from the dispatchQueue
// was sent in case a close on the Connection is being delayed
// until the queue is drained of msgs going out on the Connection.
// Even if the msg send had an error, we still signal since what we
// care about is the msg being taken from the queue.
conn.signalMsgDispatched();
// Log the msg if it was indeed sent.
if (success) logMsg(iMsg);
}
/** This method allows the caller to bypass the central dispatch
queue and have the msg directly sent out on the Connection
provided. Returns true if msg was successfully sent.
*/
protected boolean directSendMsg(Connection conn, InternalMsg iMsg)
{
// Convert the InternalMsg to an ExternalMsg before it goes
// out on the socket.
ExternalMsg eMsg = iMsg.convertToExternal();
// The Connection method will check to see if the Connection is OK.
boolean success = conn.sendMsg(eMsg.toString());
// Log the msg if it was indeed sent.
if (success) logMsg(iMsg);
return success;
}
/** Log a msg sent by the agent with any logging facilites
available to the agent. Don't log msgs being sent to any
logging agent.
*/
private void logMsg(InternalMsg iMsg) {
if (logFacilityList == null) return;
// Log the msg but don't log msgs that are
// being sent to any logging agents.
if (!logFacilityHash.containsKey(iMsg.getField(InternalMsg.RECEIVER))) {
for (int i = 0; i < logFacilityList.length; i++)
logFacilityList[i].logMsgSentByAgent(iMsg);
}
}
/** This method will add a msg to the central dispatch queue so that it
may be sent out by DispatchOutputMsgs. The Connection it is to be
sent on has its count updated to show one more msg for it is now
in the queue.
*/
// NOTE: This does not need to be synchronized. We would want to be
// careful about synchronizing in this class, especially with
// sendMessage(), since it would defeat the purpose of the
// central dispatch queue by forcing msg queueing to wait
// while a prior msg is being sent out, i.e., it would be almost
// like blocking IO to some extent.
//
protected void addMsgToDispatchQueue(Connection conn, InternalMsg iMsg)
{
dispatchQueue.addObject(iMsg);
conn.signalMsgQueuedToDispatch();
}
/** This is the DispatchOutputMsgs thread that loops forever taking a
a msg from the central dispatch queue and sending it out on the
proper Connection. The identity of the Connection is embedded in
the msg which is an InternalMsg.
*/
public void run() {
// Thread will block waiting on the dispatchQueue if it is empty.
while (true) {
InternalMsg iMsg = (InternalMsg) dispatchQueue.removeObject();
dispatchCount++;
sendMessage(iMsg);
}
}
} // end of DispatchOutputMsgs