/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1999 by Sun Microsystems, Inc.
* All rights reserved.
*
*/
// ServerDATable.java: Abstract class for DA Table in the DA/SA server.
// Author: James Kempf
// Created On: Wed May 20 08:30:46 1998
// Last Modified By: James Kempf
// Last Modified On: Tue Mar 9 12:36:37 1999
// Update Count: 124
//
/**
* ServerDATable is an abstract class that provides the interface for DA
* and scope discovery, storage of DA information from incoming DAAdverts,
* and forwarding of registrations and deregistration to DAs having
* the same scopes. A variety of implementations are possible.
* The getServerDATable() method creates the right one from a subclass.
* We keep separate track of the superclass DA table and the server
* DA table so that these two classes can co-exist in the same JVM.
* Note that the code for forwarding registrations must keep track of
* only those registrations that were done on this host. It does this
* by saving the registrations as they come in. The forwarding code
* is optimized so that forwarding of a new message is fast, while
* forwarding of a message due to discovery of a new DA is somewhat
* slower. This helps assure that SA clients get good service.
*
* in a separate thread.
*
* @author James Kempf
*/
// The active discovery object.
// The table of regs to forward. Keys are the reg URL and locale, values
// are the SSrvReg objects.
// This acts as a guard protecting an non-initialized DA table:
// If the DA Table hasn't been populated by active discovery yet,
// other threads accessing the DA table will block on readyLock.
// Keeps track of which DAs support which SPIs. The actual mapping
// is DA InetAddress to LinkedList of SPI Strings. recordNewDA
// populates this.
/**
* Get the right server DA table from the subclass.
*
* @return Table for handling DAs in the server.
*/
throws ServiceLocationException {
synchronized (readyLock) {
// Note that we are expecting this subclass. We will get a
// cast exception if somebody instantiated with a
// DATable subclass.
return (ServerDATable)daTable;
}
// Call the superclass method to link it.
// Advertise for *all* scopes. This is because we need to
// be able to support clients that do user scoping.
} // readyLock
return table;
}
/**
* Record a new DA.
*
* @param URL The DAAdvert URL.
* @param scopes The scopes.
* @param version DA version number.
* @param attrs Attributes of DA.
* @param spis SPIs supported by DA
* @return True if recorded, false if not.
*/
abstract long
long timestamp,
int version,
/**
* Return a hashtable in ServiceTable.findServices() format (e.g.
* URL's as keys, scopes as values) for DAs matching the query.
*
* @param query Query for DA attributes.
*/
throws ServiceLocationException;
/**
* Forward a registration or deregistration to all DAs that have matching
* scopes.
*
* @param msg Registration or deregistration message, server side.
* @param source The address of the source.
*/
throws ServiceLocationException {
// If the message is not from this host (on any interface)
// then don't forward it.
return;
}
// Record it so we can forward to a new DA.
} else {
}
} else {
// Only remove if tags are null. Otherwise, the updated record
// will be sought.
}
}
// We only forward registrations to v2 DAs because we are
// acting as an SA server here. There is no requirement
// for v2 SAs to communicate with v1 DAs.
// Get a hashtable of DAs that match the scopes in the message.
// We are only concerned with the unicast key, since it contains
// the DAs to which forwarding is required.
// If there are no daRecs, then simply return.
return;
}
// Otherwise, forward the registration to all DAs in the vector.
for (i = 0; i < n; i++) {
int j, m = daAddresses.size();
for (j = 0; j < m; j++) {
// Don't forward if it's the host from which the registration
// came. Otherwise, we're hosed.
}
}
}
}
// Make a key for the service agent message table.
}
/**
* Handle an incoming DAAdvert. Presence must be recorded in the
* implementation specific server DA table and any registrations need
* to be forwarded if the boot timestamp is different from the
* old boot timestamp.
*
* @param advert Incoming DAAdvert.
*/
// Remove if DA is going down.
if (advert.isGoingDown()) {
try {
} catch (UnknownHostException ex) {
return;
}
if (conf.traceDATraffic()) {
new Object[] {
}
}
} else {
// verify the DAAdvert
try {
} catch (ServiceLocationException e) {
}
return;
}
}
long timestamp =
// Don't forward if the advert was rejected, or if the
// old timestamp greater than or equal to the new timestamp.
// If the old timestamp is greater than or equal to the new,
// it means that we have already forwarded to this DA.
// IF the old timestamp is less, it means that
// the DA has crashed and come up again since we last saw
// it, so we may have missed forwarding something to it.
if (conf.traceDATraffic()) {
new Object[] {
}
return;
}
if (conf.traceDATraffic()) {
new Object[] {
}
// Forward existing registrations to the new advert.
}
}
//
// Private methods.
//
private void
long timestamp,
int version) {
// Wait a random amount of time before forwarding.
try {
} catch (InterruptedException ex) {
}
// Get the registrations to forward.
// Get the address of the DA.
try {
} catch (UnknownHostException ex) {
new Object[] {
host});
}
return;
}
try {
} catch (ServiceLocationException ex) {
// By this time, we should have it.
}
// Forward the registrations. Keep track of any deleted elements.
while (regs.hasMoreElements()) {
} else {
}
// Get the record and modify the reg to reflect the
// record. We must do this because the SA may have
// changed the record since it was first registred
// and we do not keep track of the changes here.
// If the record is null, it means that the entry was
// aged out.
} else {
// Check that the scopes match.
continue;
}
}
}
}
// Remove any deleted elements from the hashtable.
// We do this in a separate loop because enumerations
// aren't synchronized.
for (i = 0; i < n; i++) {
} else {
}
}
}
// Forward the registration or deregistration to the URL.
// Don't forward to myself! Otherwise, nasty recursion happens.
return;
}
// If security is on, only forward if this DA can verify the authblocks
if (conf.getHasSecurity()) {
// internal error; skip this DA to be safe
return;
}
} else {
// shouldn't even be forwarding this!
return;
}
// If each authblock is equiv to at least one SPI, forward the reg
while (abs.hasMoreElements()) {
// check each DA SPI
boolean daSPImatch = false;
daSPImatch = true;
break;
}
}
if (!daSPImatch) {
return;
}
}
}
if (conf.traceDATraffic()) {
new Object[] {
addr});
}
// Send it via TCP. DAs should understand TCP, and it's reliable.
try {
// Construct the client side message, for outgoing.
}
} catch (ServiceLocationException ex) {
if (conf.traceDATraffic()) {
new Object[] {
addr,
ex.getMessage()});
}
}
// Report any errors.
if (conf.traceDATraffic()) {
new Object[] {
addr,
}
}
}
}