001: /*
002: * HostChooser.java
003: *
004: * Created on July 25, 2002, 6:01 PM
005: */
006:
007: // TODO : TBD !!!
008: package com.sun.portal.rproxy.configservlet.client;
009:
010: /*
011: * Implements a simple round-robin algorithm based on iterators,
012: * Also registers itself to be notified for HostAvailabilityEvents both
013: * from com.sun.portal.rproxy.connectionhandler.ServerList and
014: * com.sun.portal.configservlet.client.SrapClient.
015: *
016: * @author Rajesh T
017: * @version
018: */
019: import java.io.IOException;
020: import java.net.MalformedURLException;
021: import java.net.URL;
022: import java.util.ArrayList;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.StringTokenizer;
028: import java.util.logging.Level;
029: import java.util.logging.Logger;
030:
031: import com.sun.portal.log.common.PortalLogger;
032: import com.sun.portal.util.HostAvailabilityEvent;
033: import com.sun.portal.util.HostAvailabilityListener;
034: import com.sun.portal.util.HostChecker;
035: import com.sun.portal.util.ServiceConstants;
036: import com.sun.portal.util.SystemProperties;
037:
038: public class HostChooser extends HostAvailabilityListener implements
039: ServiceConstants {
040:
041: private static final String REMOTE_CONFIG_SERVLET = "/RemoteConfigServlet";
042:
043: private static List GATEWAY_DSAME_AGENTS = new ArrayList();
044:
045: private static String SERVLET_URL = "";
046:
047: private String path = null;
048:
049: private List portalServers = null;
050:
051: private Iterator roundRobin = null;
052:
053: private static int orginalSize = 0;
054:
055: private Map unavailableServers = new HashMap();
056:
057: private static Logger logger = PortalLogger
058: .getLogger(HostChooser.class);
059:
060: /*
061: * register for events when created
062: */
063:
064: public HostChooser() {
065:
066: // Get the list of all agent URL's mentioned in the dsame agents list in
067: // platform.conf
068: String dsameAgents = SystemProperties
069: .get("gateway.dsame.agent");
070: StringTokenizer tokenizer = new StringTokenizer(dsameAgents,
071: ",");
072:
073: while (tokenizer.hasMoreElements()) {
074: String agent = (String) tokenizer.nextElement();
075: GATEWAY_DSAME_AGENTS.add(agent);
076: try {
077: URL url = new URL(agent);
078: if (isAvailable(url)) {
079: path = url.getPath();
080: SERVLET_URL = agent;
081: addHostAvailabilityListener(this );
082: }
083: } catch (MalformedURLException me) {
084: logger.severe("PSSRRPROXY_CSPRCSERVLETC003");
085: }
086: }
087: }
088:
089: private boolean isAvailable(URL url) {
090: boolean ret = false;
091: try {
092: url.openConnection().connect();
093: ret = true;
094: } catch (IOException e) {
095: logger.log(Level.INFO, "Url " + url + " is not available.");
096: }
097: return ret;
098: }
099:
100: private synchronized void initialize() {
101: Iterator itr = GatewayProfile.getStringList("PortalServerList")
102: .iterator();
103: portalServers = new ArrayList();
104: while (itr.hasNext()) {
105: portalServers.add(itr.next().toString().toLowerCase()
106: + REMOTE_CONFIG_SERVLET);
107: }
108: roundRobin = portalServers.iterator();
109: }
110:
111: /*
112: * @ returns the next available host based on round-robin algorithm
113: */
114:
115: public synchronized String getHost() {
116: int count = 0;
117: if (portalServers == null) {
118: try {
119: initialize();
120: } catch (NullPointerException ne) {
121:
122: /*
123: * Will be thrown when the gateway comes up since GW profile is
124: * there in the portal server and hance the first profile
125: * request is the gateway profile read at that point Gateway
126: * Profile is always null; so return as defined in
127: * platform.conf.instance_name
128: */
129:
130: return SERVLET_URL;
131: }
132:
133: /*
134: * No of portal servers as defined in the profile
135: */
136: orginalSize = portalServers.size();
137: }
138:
139: String retval = null;
140:
141: while (count < orginalSize) {
142: String host = getHostImpl();
143: if (isAvailable(host)) {
144: retval = host;
145: break;
146: }
147: count++;
148: }
149: return retval;
150: }
151:
152: private synchronized String getHostImpl() {
153:
154: if (portalServers.size() == 0
155: || portalServers.size() == unavailableServers.size()) {
156: /*
157: * All all portal servers has gone down. After the gateway started
158: */
159: return null;
160: }
161: if (orginalSize < 2) {
162:
163: /*
164: * less than two servers so single GW single portal instance so skip
165: * round robin
166: */
167: return SERVLET_URL;
168:
169: } else {
170: if (roundRobin == null) {
171: roundRobin = portalServers.iterator();
172: }
173: }
174:
175: if (roundRobin.hasNext()) {
176: return (roundRobin.next().toString());
177: } else {
178: roundRobin = portalServers.iterator();
179: return (roundRobin.next().toString());
180: }
181: }
182:
183: /*
184: * checks whether the specified server is there in the available list. Added
185: * to maintain stickness to portal server
186: */
187:
188: public boolean isAvailable(String host) {
189: try {
190: if (portalServers == null) {
191: initialize();
192: }
193:
194: URL tmpurl = new URL(host);
195: StringBuffer portalHost = new StringBuffer();
196: portalHost.append(tmpurl.getProtocol()).append("://")
197: .append(tmpurl.getHost()).append(":");
198: // append(":").append(tmpurl.getPort());
199:
200: int iPort = tmpurl.getPort();
201: if (iPort == -1) {
202: if ((tmpurl.getProtocol()).equalsIgnoreCase("http")) {
203: portalHost
204: .append(ServiceConstants.DEFAULT_HTTP_PORT);
205: } else if ((tmpurl.getProtocol())
206: .equalsIgnoreCase("https")) {
207: portalHost
208: .append(ServiceConstants.DEFAULT_HTTPS_PORT);
209: }
210:
211: } else {
212: portalHost.append(iPort);
213: }
214:
215: String requestedHost = portalHost.toString().toLowerCase();
216:
217: synchronized (unavailableServers) {
218: if (!unavailableServers.isEmpty()
219: && unavailableServers.get(requestedHost) != null) {
220: return false; // do not use it!
221: }
222: }
223:
224: URL url = new URL(requestedHost);
225:
226: return HostChecker.isHostAvailable(url,
227: HostAvailabilityEvent.PS_HOST);
228: } catch (MalformedURLException mue) {
229: return false;
230: }
231: }
232:
233: /*
234: * @returnd the gateway servlet installation path
235: */
236:
237: public String getPath() {
238: return path;
239: }
240:
241: /*
242: * updates it availabilty server list based on event received
243: */
244:
245: public void hostAvailabilityChanged(HostAvailabilityEvent hae) {
246: if (portalServers == null) {
247: initialize();
248: }
249: if (hae.getHostType() == HostAvailabilityEvent.PS_HOST) {
250: if (hae.getHostStatus() == HostAvailabilityEvent.HOST_AVAILABLE) {
251: //Begin CR6312991
252: //addHost(hae.getHost());
253: removeHost(hae.getHost());
254: } else if (hae.getHostStatus() == HostAvailabilityEvent.HOST_UNAVAILABLE) {
255: //removeHost(hae.getHost());
256: addHost(hae.getHost());
257: //End CR6312991
258: }
259: }
260: }
261:
262: /*
263: * removes the server from the unavailable list
264: */
265:
266: private void removeHost(String host) {
267: synchronized (unavailableServers) {
268: if (!unavailableServers.isEmpty()
269: && unavailableServers.get(host) != null) {
270: unavailableServers.remove(host);
271: }
272: }
273: }
274:
275: /*
276: * adds a server to the unavailable list
277: */
278:
279: private void addHost(String host) {
280: synchronized (unavailableServers) {
281: if (unavailableServers.isEmpty()
282: || unavailableServers.get(host) == null) {
283: unavailableServers.put(host, new Long(System
284: .currentTimeMillis()));
285: }
286: }
287: }
288:
289: /*
290: * @ returns the boot path (Remote Config servlet URL) as sepecified in the
291: * platform.conf. <instance_name> Used only to fetch the GW's profile during
292: * the GW boot up process rest of the requests get's load balanced across
293: * portal servers in case there are multiple portal instances @ see
294: * SrapClient.bootupExecute() @ used
295: * com.sun.portal.rproxy.configservlet.GatewayProfile @ used
296: * com.sun.portal.rproxy.configservlet.PlatformProfile
297: */
298:
299: public static String getBootupPortalServer() {
300: return SERVLET_URL;
301: }
302: }
|