001: /*
002: * <copyright>
003: *
004: * Copyright 2001-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.pizza.relay;
028:
029: import org.cougaar.core.mts.MessageAddress;
030: import org.cougaar.core.persist.NotPersistable;
031: import org.cougaar.core.relay.Relay;
032: import org.cougaar.core.util.UID;
033: import org.cougaar.core.util.UniqueObject;
034: import org.cougaar.pizza.Constants;
035: import org.cougaar.pizza.plugin.PizzaPreferences;
036: import org.cougaar.util.log.Logger;
037: import org.cougaar.util.log.Logging;
038:
039: import java.util.HashSet;
040: import java.util.Set;
041:
042: /**
043: * A source-side {@link Relay} for RSVPs.
044: * <p/>
045: * As responses come back from remote agents, the infrastrusture (RelayLP) calls updateResponse(),
046: * and entries are added to the {@link PizzaPreferences} object.
047: *
048: * @see org.cougaar.pizza.plugin.InvitePlugin
049: * @see org.cougaar.pizza.plugin.PizzaPreferences
050: */
051: public class RSVPRelaySource implements Relay.Source, UniqueObject {
052: private final Object query; // The query in our RSVP -- meat or veg?
053: private final UID uid;
054:
055: private final long creationTime = System.currentTimeMillis();
056:
057: /**
058: * The set of target addresses - in this case, only one: the ABA.
059: * @see org.cougaar.multicast.AttributeBasedAddress
060: */
061: private Set targets = new HashSet();
062:
063: /** The source-side accumulation of RSVPs, so we can automatically accumulate responses. */
064: private PizzaPreferences pizzaPreferences;
065:
066: /**
067: * A static logger for all RSVPRelaySource objects.
068: * Note that this is a nice way to use the Cougaar logger from an object that
069: * is not a Component, and therefore can't easily get an instance of the LoggingService.
070: */
071: private static Logger classLogger = Logging
072: .getLogger(RSVPRelaySource.class);
073:
074: /**
075: * Create a new Relay Source whose content is the query, and which will
076: * accumulate responses in the given {@link PizzaPreferences} object.
077: */
078: public RSVPRelaySource(UID uid, MessageAddress target,
079: Object query, PizzaPreferences pizzaPreferences) {
080: this .uid = uid;
081: this .query = query;
082: this .pizzaPreferences = pizzaPreferences;
083: targets.add(target);
084: }
085:
086: /**
087: * Who gets this invitation?
088: *
089: * @return set of targets (For us, just one member - the AttributeBasedAddress)
090: */
091: public Set getTargets() {
092: return targets;
093: }
094:
095: /**
096: * The query in the relay.
097: *
098: * @return the query in the RSVP - meat or veg?
099: */
100: public Object getContent() {
101: return query;
102: }
103:
104: /**
105: * Get the Factory for RSVPTargets.
106: * <p/>
107: * This factory creates a stand-alone Relay.Target implementation, simply
108: * copying over the content (our query). If we implemented the Relay.Target
109: * and Relay.Source in the same Class, we'd want to ensure
110: * that the target had an empty set of target addresses, to
111: * avoid re-propagating the Relay from the target agents.
112: *<p>
113: * If your Relay.Target was also a Relay.Source and <i>did</i>
114: * include target addresses, this could lead to endless pinging in this case
115: * where the target address is an ABA broadcast to all members of the
116: * community.
117: *
118: * @return target factory that makes a stand-alone Relay Target
119: */
120: public TargetFactory getTargetFactory() {
121: return RSVPTargetRelayFactory.getTargetFactory();
122: }
123:
124: /**
125: * Record responses from remote agents as they come in on the {@link PizzaPreferences}
126: * object.
127: * <p/>
128: * Note that we assume the response will be a {@link RSVPReply}.
129: * <p/>
130: * If INFO logging is on, tells how long we had to wait until all responses
131: * came back.
132: *
133: * @return Relay.RESPONSE_CHANGE - since every time we get a response, we
134: * want to examine it
135: */
136: public int updateResponse(MessageAddress target, Object response) {
137: RSVPReply rsvpReply = (RSVPReply) response;
138:
139: // Accumulate the response automatically
140: pizzaPreferences.addFriendToPizza(rsvpReply.getFriend(),
141: rsvpReply.getPizzaPreference());
142:
143: // INFO logging of what we have so far.
144: if (classLogger.isInfoEnabled()) {
145: classLogger.info("RSVPRelaySource - pizza prefs now : "
146: + pizzaPreferences);
147:
148: if ((pizzaPreferences.getNumMeat() + pizzaPreferences
149: .getNumVeg()) == Constants.EXPECTED_NUM_FRIENDS) {
150: classLogger
151: .info("Waited "
152: + ((System.currentTimeMillis() - creationTime) / 1000)
153: + " seconds to get responses back from "
154: + Constants.EXPECTED_NUM_FRIENDS
155: + " friends (including party planner).");
156: }
157: }
158:
159: return Relay.RESPONSE_CHANGE;
160: }
161:
162: /**
163: * @return the {@link PizzaPreferences} object in which our answers are collected
164: */
165: public PizzaPreferences getPizzaPrefs() {
166: return pizzaPreferences;
167: }
168:
169: /**
170: * Implemented for UniqueObject interface.
171: * @return the UID of this UniqueObject.
172: **/
173: public UID getUID() {
174: return uid;
175: }
176:
177: /**
178: * Does nothing - not allowed to reset UID.
179: * Implemented for UniqueObject interface.
180: **/
181: public void setUID(UID uid) {
182: }
183:
184: public String toString() {
185: return "RSVPRelaySource: " + " query=" + getContent()
186: + " target=" + targets + " preferences="
187: + pizzaPreferences;
188: }
189: }
|