001: /*
002: * <copyright>
003: *
004: * Copyright 2002-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.core.wp.bootstrap.config;
028:
029: import java.util.Iterator;
030: import java.util.Map;
031: import org.cougaar.core.component.Component;
032: import org.cougaar.core.component.ServiceBroker;
033: import org.cougaar.core.component.ServiceRevokedListener;
034: import org.cougaar.core.service.LoggingService;
035: import org.cougaar.core.service.ThreadService;
036: import org.cougaar.core.thread.Schedulable;
037: import org.cougaar.core.wp.bootstrap.Bundle;
038: import org.cougaar.core.wp.bootstrap.ConfigService;
039: import org.cougaar.core.wp.bootstrap.DiscoveryService;
040: import org.cougaar.util.GenericStateModelAdapter;
041:
042: /**
043: * This component copies bundles found in the {@link ConfigService}
044: * to the {@link DiscoveryService}.
045: * <p>
046: * This is the simple static bootstrap.
047: */
048: public class ConfigDiscovery extends GenericStateModelAdapter implements
049: Component, DiscoveryService.Client {
050: private ServiceBroker sb;
051:
052: private LoggingService log;
053: private ThreadService threadService;
054: private Schedulable thread;
055:
056: private DiscoveryService discoveryService;
057:
058: private ConfigService configService;
059:
060: public void setServiceBroker(ServiceBroker sb) {
061: this .sb = sb;
062: }
063:
064: public void setLoggingService(LoggingService log) {
065: this .log = log;
066: }
067:
068: public void setThreadService(ThreadService threadService) {
069: this .threadService = threadService;
070: }
071:
072: public void load() {
073: super .load();
074:
075: configService = (ConfigService) sb.getService(this ,
076: ConfigService.class, null);
077: if (configService == null) {
078: throw new RuntimeException("Unable to obtain ConfigService");
079: }
080:
081: discoveryService = (DiscoveryService) sb.getService(this ,
082: DiscoveryService.class, null);
083: if (discoveryService == null) {
084: throw new RuntimeException(
085: "Unable to obtain DiscoveryService");
086: }
087: }
088:
089: public void unload() {
090: if (discoveryService != null) {
091: sb.releaseService(this , DiscoveryService.class,
092: discoveryService);
093: discoveryService = null;
094: }
095: if (configService != null) {
096: sb.releaseService(this , ConfigService.class, configService);
097: configService = null;
098: }
099: if (threadService != null) {
100: // halt our threads?
101: sb.releaseService(this , ThreadService.class, threadService);
102: threadService = null;
103: }
104:
105: super .unload();
106: }
107:
108: public void startSearching() {
109: final Map m = configService.getBundles();
110: if (log.isDetailEnabled()) {
111: log.detail("startSearching, ds.update(" + m + ")");
112: }
113: if (m == null || m.isEmpty()) {
114: return;
115: }
116:
117: discoveryService.update(m);
118:
119: // wake up before the earliest TTD, to make sure our entries stay alive in
120: // the cache. This can happen if the server is temporarily unreachable
121: // for a relatively long time.
122: boolean set_min_ttd = false;
123: long min_ttd = -1;
124: for (Iterator iter = m.values().iterator(); iter.hasNext();) {
125: long ttd = ((Bundle) iter.next()).getTTD();
126: if (ttd > 0 && (!set_min_ttd || ttd < min_ttd)) {
127: set_min_ttd = true;
128: min_ttd = ttd;
129: }
130: }
131: if (set_min_ttd) {
132: Runnable r = new Runnable() {
133: public void run() {
134: // TODO if we have a range of TTDs then we should only update the
135: // map subset that will expire at this time, and set our timer to
136: // wake us accordingly. However, that's overkill -- we'll simply
137: // recache all our bundles.
138: if (log.isDetailEnabled()) {
139: log.detail("renew config bootstrap");
140: }
141: discoveryService.update(m);
142: }
143: };
144: thread = threadService.getThread(this , r,
145: "WP config bootstrap");
146: long delay = Math.max(1000, (long) (0.9 * min_ttd));
147: thread.scheduleAtFixedRate(delay, delay);
148: }
149: }
150:
151: public void stopSearching() {
152: if (log.isDetailEnabled()) {
153: log.detail("stopSearching");
154: }
155: if (thread != null) {
156: thread.cancelTimer();
157: thread = null;
158: }
159: }
160: }
|