ServiceStoreInMemory.java revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
*/
/*
* ident "%Z%%M% %I% %E% SMI"
*
* Copyright 2001,2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
*/
// SCCS Status: %W% %G%
// ServiceStoreInMemory.java: An in-memory implementation
// of the service store.
// Author: James Kempf
// Created On: Mon Oct 20 12:36:35 1997
// Last Modified By: James Kempf
// Last Modified On: Tue Mar 2 15:32:23 1999
// Update Count: 472
//
/**
* The ServiceStoreInMemory class implements the ServiceStore interface
* on in-memory data structures.
* <details of those structures here>
*
* @version %R%.%L% %D%
* @author James Kempf
*/
/**
* The BVCollector interface allows various
* data structures to collect stuff from the BtreeVector.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
private interface BVCollector {
// Set the return value.
}
/**
* The ParserBVCollector class implements a BtreeVector
* collector for the parser.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
}
// Add if we don't already have it.
// Need to adjust lifetime to reflect the time to live. Don't
// set the lifetime if it has already expired.
long lifetime =
(rec.getExpirationTime() -
if (lifetime > 0) {
}
}
}
}
}
/**
* The AttributeBVCollector class implements a BtreeVector
* collector for the collecting attribute values by type.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
// records already seen.
}
// If we've got it already, then don't add again.
try {
} catch (ServiceLocationException ex) {
"ssim_attrbvc_botch",
}
}
}
}
/**
* The ScopeBVCollector class implements a BtreeVector
* collector for the collecting records if scopes match.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
// for those we've seen
}
// If we've got it already, then don't add.
} else {
// Check scopes.
int i;
for (i = 0; i < len; i++) {
break;
}
}
}
}
}
}
/**
* The AllBVCollector class implements a BtreeVector
* collector for collecting all records.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
}
// If we've got it already, then don't add.
}
}
}
/**
* The List class implements a linked list for storing records
* in the BtreeVector structure.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
// Create a new list object.
}
// Insert a new record after this one. Return the new
// record.
}
return newRec;
}
// Delete this record from the list.
synchronized void delete() {
}
}
}
}
/**
* The RegRecord class implements a record with the value for the
* record buckets. It is used as elements in BtreeVector.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
// never changes.
// Construct a new one.
}
// Add a new record to the buckets, return new element.
}
// For every element in record's list, set the return value in the
// returns object. Since deletions may have removed everything
// from this record, return true only if something was there.
boolean match = false;
match = true;
}
return match;
}
}
}
/**
* The BtreeVector class stores registrations in sorted order. The
* Quicksort algorithm is used to insert items and search for something.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
private class BtreeVector extends Object {
// Contains the sorted vector.
}
// Return the contents as a sorted vector of RegRecord.
// Note that this doesn't return a copy, so
// the vector can be side-effected.
Vector getContents() {
return contents;
}
// Add the entire contents of the vector to the return record.
boolean match = false;
for (i = 0; i < n; i++) {
}
return match;
}
// Add a new record to this vector. We also garbage collect any
// records that are empty. Return the list object added.
// Add the record to this one.
}
// Add only if no element in the vector matches the tag.
// Go through the vector, putting in anything that isn't equal.
boolean match = false;
for (i = 0; i < n; i++) {
// Add to prospective returns.
}
}
// If we got this far, there are some no matches.
for (i = 0; i < n; i++) {
}
return match;
}
boolean
boolean match = false;
// We can't walk the vector if the value is an AttributePattern,
// because equals doesn't apply.
if (pattern instanceof AttributePattern) {
for (i = 0; i < n; i++) {
}
}
} else {
// not an update...
// If nothing came back, return false.
match = false;
} else {
// Otherwise set returns in the vector.
}
}
return match;
}
boolean
// Go through the vector, putting in anything that isn't equal.
boolean match = false;
for (i = 0; i < n; i++) {
}
}
return match;
}
boolean
// Go through the vector, putting in anything that is
// less than or equal.
boolean match = false;
for (i = 0; i < n; i++) {
break;
}
}
return match;
}
boolean
// Go through the vector, putting in anything that is not
// less than or equal. Start at the top.
boolean match = false;
for (i = n - 1; i >= 0; i--) {
break;
}
}
return match;
}
boolean
// Go through the vector, putting in anything that is greater
// than or equal. Start at the top.
boolean match = false;
for (i = n - 1; i >= 0; i--) {
break;
}
}
return match;
}
boolean
// Go through the vector, putting in anything that is not
// than or equal.
boolean match = false;
for (i = 0; i < n; i++) {
break;
}
}
return match;
}
// Binary tree walk the vector, performing the operation. Note that
// we use dynamic typing heavily here to get maximum code reuse.
private RegRecord
// Get the starting set of indicies.
int bottom = 0;
while (size > 0) {
// Get the one at the current middle.
// Garbage Collection.
// If it was null, then delete. But only if we're
// inserting. We leave it alone on lookup.
if (update) {
continue;
}
}
// Compare value to record, if equal, return record.
// code.
return rec;
// Recalculate index. We move left, because the value is
// less that the value in the vector, so an equal value
// must be to the left. Note that the top is not in the
// interval because it has already been checked and
// found wanting.
// Neither top nor middle are in the interval,
// so size is zero. We need to compare with bottom.
if (update) {
// If the pattern is equal to bottom, return it.
// If the pattern is less than or equal to bottom,
// we insert it at bottom. If it is greater
// than or equal, we insert it at middle.
return trec;
// Pattern is less than bottom, so insert
// at bottom.
} else {
}
} else {
// If it equals bottom, then return bottom rec.
}
}
break;
}
// Recalculate index. We move right, because the value is
// greater that the value in the vector, so an equal
// value must be to the right. Note that the top is not
// in the interval because it has already been checked
// and found wanting.
// Neither bottom nor middle is in the interval,
// so size is zero. We need to compare with top.
if (update) {
// If the pattern is equal to the top, we
// return the top. If the pattern is greater
// then top, we insert it after top, else we
// insert it at top.
return trec;
} else if (compareGreaterEqual(pattern,
// Pattern is greater than top, so insert
// after top.
int i = top + 1;
} else {
}
} else {
// Pattern is less than top, so insert at
// top, causing top to move up.
}
} else {
// If it equals top, then return top rec.
}
}
break;
}
}
}
// Take care of update where vector is empty or cleaned out.
"ssim_btree_botch",
new Object[0]);
}
return rec;
}
// Add any registrations that match the pattern.
boolean
return true;
}
} else if (target instanceof AttributeString) {
// If the pattern is an AttributePattern instead of an
// AttributeString, the subclass method will get invoked.
(AttributeString)target)) {
return true;
}
} else {
"ssim_unk_qtype",
}
return false;
}
// Add any registrations that are less than or equal to the pattern.
boolean
return true;
}
} else if (target instanceof AttributeString) {
(AttributeString)pattern)) {
return true;
}
return true;
}
return true;
}
} else {
"ssim_unk_qtype",
}
return false;
}
// Add any registrations that are greater than or equal to the pattern.
boolean
return true;
}
} else if (target instanceof AttributeString) {
(AttributeString)pattern)) {
return true;
}
return true;
}
return true;
}
} else {
"ssim_unk_qtype",
}
return false;
}
}
/**
* The InMemoryEvaluator evaluates queries for ServiceStoreInMemory.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
attrLevelNot = btv;
}
// Evaluate the query by matching the attribute tag and
// value, using the operator. If invert is true, then
// return records that do NOT match.
public boolean
char op,
boolean invert,
throws ServiceLocationException {
boolean match = false;
// If inversion is on, then gather all from the
// table of registrations that do NOT have this
// attribute.
if (invert) {
}
// Find the table of classes v.s. sorted value vectors.
// If attribute not present, then simply return.
return match;
}
// If operator is present, then return all.
// ...but only if invert isn't on.
if (!invert) {
// We use attrLevelNot to get all, because it
// will also pick up keywords. There are
// no keywords in attrLevel because keywords
// don't have any values.
}
return match;
}
// We know that the type table is fully initialized with
// BtreeVectors for each type.
// Get the pattern's class. Pattern will not be null because
// the parser has checked for it and PRESENT has been
// filtered out above.
// If the class is AttributePattern, then use AttributeString
// instead.
if (pattern instanceof AttributePattern) {
}
// If invert is on, collect those whose types don't match as
// well.
if (invert) {
while (en.hasMoreElements()) {
// Only record if the type does NOT match.
}
}
}
// Get the sorted value vector corresponding to the value class.
// Do the appropriate thing for the operator.
switch (op) {
if (!invert) {
} else {
}
break;
// Note that we've filtered out Opaque, Boolean, and wildcarded
// strings before calling this method.
if (!invert) {
} else {
}
break;
// Note that we've filtered out Opaque and Boolean
// before calling this method.
if (!invert) {
} else {
}
break;
default:
"ssim_unk_qop",
}
return match;
}
}
/**
* The ServiceRecordInMemory class implements the
* ServiceStore.ServiceRecord interface on in-memory data structures.
* Each property is implemented as an instance variable.
*
* @version %R%.%L% %D%
* @author James Kempf
*/
private class ServiceRecordInMemory extends Object
implements ServiceStore.ServiceRecord {
// URL signature block list, if any.
// Attribute signature block list, if any.
// Create a ServiceStoreInMemory record.
// All need to be nonnull.
serviceURL = surl;
}
/**
* Return the ServiceURL for the record.
*
* @return The record's service URL.
*/
public final ServiceURL getServiceURL() {
return serviceURL;
}
/**
* Return the Vector of ServerAttribute objects for the record.
*
* @return Vector of ServerAttribute objects for the record.
*/
public final Vector getAttrList() {
return attrList;
}
/**
* Return the locale of the registration.
*
* @return The locale of the registration.
*/
return locale;
}
/**
* Return the Vector of scopes in which the record is registered.
*
* @return Vector of strings with scope names.
*/
return scopes;
}
/**
* Return the expiration time for the record. This informs the
* service store when the record should expire and be removed
* from the table.
*
* @return The expiration time for the record.
*/
public long getExpirationTime() {
return timeToDie;
}
/**
* Return the URL signature list.
*
* @return URL signature block list.
*/
public Hashtable getURLSignature() {
return urlSig;
}
/**
* Return the attribute signature list.
*
* @return Attribute signature list.
*/
public Hashtable getAttrSignature() {
return attrSig;
}
//
// Package-local methods.
}
}
}
}
ret +=
ret += "}";
return ret;
}
// Convert a vector of ServiceLocationAttribute objects to
// ServerAttibutes.
private Vector
for (i = 0; i < n; i++) {
}
return v;
}
}
/**
* A record for scopeTypeLangTable table,
*
* @version %R%.%L% %D%
* @author James Kempf
*/
// Table of attributes, sorted by value.
boolean isAbstract = false;
// True if the record is for an abstract
// type.
STLRecord(boolean isAbstract) {
this.isAbstract = isAbstract;
}
}
//
// ServiceStoreInMemory instance variables.
//
// ServiceStoreInMemory maintains an invaraint that the record for a
// particular URL, set of scopes, and locale is the same object
// (pointer-wise) regardless of where it is inserted into the table.
// So it can be compared with ==.
// The scopeTypeLangTable
//
// STLRecord objects. The STLRecord.attrValueSort field is a Hashtable
// where all registrations *having* the attribute tag keys in the
// table are contained. This table is used in queries for positive
// logical expressions. The STLRecord.attrSort field is a BtreeVector
// keyed by attribute. It is used for negative queries to find all
// records not having a particular attribute and to find all
// registrations. The STLRecord.isAbstract field tells whether the record
// is for an abstract type name.
//
// The values in the STLRecord.attrValueSort hashtable are themselves
// hashtables. These hashtables are keyed by one of the type keys below,
// with the values being BtreeVector objects. The BtreeVector objects
// contain sorted lists of RegRecord objects for Integer,
// AttributeString, Boolean, and Opaque types. All records having
// values equal to the value in the RegRecord are put into a list
// on the RegRecord. There is no STLRecord.attrValueSort
// hashtable for keyword attributes because they have no values.
// The parser evaluator must use the STLRecord.attrSort hashtable when a
// present operator is encountered (the only valid operator with a
// keyword).
//
// The values in the STLRecord.attrSort BtreeVector are RegRecord
// objects with all records having that attribute tag being on the
// RegRecord list.
// Keys for the various types.
private final static String ATTRIBUTE_STRING_TYPE =
"com.sun.slp.AttributeString";
// The urlScopeLangTable
//
// Keys for this table are service url as a string. We don't use
// the service URL itself because the hash code depends on the
// current service type rather than the original, and we need
// to be able to distinguish for a non-service: URL if a
// registration comes in with a different service type from the
// original. Values are hashtables with key being scope name,
// values are hashtables with lang tag key. Ultimate values are
// a vector of List objects for lists in which List.record is
// inserted. This table is used to perform deletions and for
// finding the attributes associated with a particular URL.
// The sstLocales Table
//
// Values in the lang tag table are Integer objects giving
// given locale.
// A queue of records sorted according to expiration time.
// Constants that indicate whether there are any registrations.
private final static int NO_REGS = 0;
private final static int NO_REGS_IN_LOCALE = 1;
private final static int REGS_IN_LOCALE = 2;
// Boot time. For DAAdvert timestamps.
//
// ServiceStore Interface Methods.
//
/**
* Return the time since the last stateless reboot
* of the ServiceStore.
*
* @return A Long giving the time since the last stateless reboot,
* in NTP format.
*/
public long getStateTimestamp() {
return bootTime;
}
/**
* Age out all records whose time has expired.
*
* @param deleted A Vector for return of ServiceStore.Service records
* containing deleted services.
* @return The time interval until another table walk must be done,
* in milliseconds.
*
*/
// Get the ageOut queue and remove all records whose
// time has popped.
// Go through the queue, dropping records that
// have expired.
int i;
// Break out when none expire now.
break;
}
// Remove the element from the queue.
/*
* Must decrement the index 'i' otherwise the next iteration
* around the loop will miss the element immediately after
* the element removed.
*
* WARNING: Do not use 'i' again until the loop has
* iterated as it may, after decrementing,
* be negative.
*/
queue.removeElementAt(i);
i--;
// Deregister all on this list. We
// take specific care to save the next
// list element before we deregister, otherwise
// it will be gone after the deregister.
while (l != null) {
if (traceDrop) {
new Object[] {
url,
rec.getAttrList(),
}
// Save the record for the service table, in case more
// processing needed.
// Save l.next NOW before deregisterInternal() removes it!
l = l.next;
}
}
// Calculate the new sleep time. If there's anything in the vector,
// then use element 0, because the vector is sorted by time
// and that will be minimum. Otherwise, use the maximum.
// it will wake right up, but
// so what?
}
return newSleepy;
}
/**
* Create a new registration with the given parameters.
*
* @param url The ServiceURL.
* @param attrs The Vector of ServiceLocationAttribute objects.
* @param locale The Locale.
* @param scopes Vector of scopes in which this record is registered.
* @param urlSig auth block Hashtable for URL signature, or null if none.
* @param attrSig auth block Hashtable for URL signature, or null if none.
* @return True if there is an already existing registration that
* this one replaced.
* @exception ServiceLocationException Thrown if any
* error occurs during registration or if the table
* requires a network connection that failed. This
* includes timeout failures.
*/
synchronized public boolean
throws ServiceLocationException {
boolean existing = false;
// Find an existing record, in any set of scopes having this language.
// Deregister from existing scopes, if there is an existing record.
// Ensure that the rereg SPI set and the record's SPI set are
// equivalent. We need only check the URL sigs here, since
// this operation is equivalent to a dereg followed by a reg,
// and dereg requires only URL auth blocks.
while (spis.hasMoreElements()) {
throw new ServiceLocationException(
"not_all_spis_present",
}
}
// not all required SPIs were present in SrvReg
throw new ServiceLocationException(
"not_all_spis_present",
}
}
existing = true;
}
// Create a new record to register.
// Add new registration.
return existing;
}
/**
* Deregister a ServiceURL from the database for every locale
* and every scope. There will be only one record for each URL
* and locale deregistered, regardless of the number of scopes in
* which the URL was registered, since the attributes will be the
* same in each scope if the locale is the same.
*
* @param url The ServiceURL
* @param scopes Vector of scopes.
* @param urlSig The URL signature, if any.
* @exception ServiceLocationException Thrown if the
* ServiceStore does not contain the URL, or if any
* error occurs during the operation, or if the table
* requires a network connection that failed. This
* includes timeout failures.
*/
synchronized public void
throws ServiceLocationException {
// Find existing record. Any locale will do.
// Error if none.
throw
"ssim_no_rec",
}
// verify that the dereg SPI set and the record's SPI set are
// equivalent
while (spis.hasMoreElements()) {
throw new ServiceLocationException(
"not_all_spis_present",
}
}
// not all required SPIs were present in SrvDereg
throw new ServiceLocationException(
"not_all_spis_present",
}
}
/*
* Deregister the URL for all locales. Use the recorded service URL
* because the one passed by the client is possibly incomplete e.g.
* lacking the service type.
*/
}
/**
* Update the service registration with the new parameters, adding
* attributes and updating the service URL's lifetime.
*
* @param url The ServiceURL.
* @param attrs The Vector of ServiceLocationAttribute objects.
* @param locale The Locale.
* @param scopes Vector of scopes in which this record is registered.
* @exception ServiceLocationException Thrown if any
* error occurs during registration or if the table
* requires a network connection that failed. This
* includes timeout failures.
*/
synchronized public void
throws ServiceLocationException {
// Error if none.
throw
"ssim_no_rec",
}
// If this is a nonServiceURL, check whether it's registered
// under a different service type.
if (!type.isServiceURL()) {
}
// Deregister the URL in this locale.
// Create a new record to update.
// Merge old record into new.
// Add the new record.
}
/**
* Delete the attributes from the ServiceURL object's table entries.
* Delete for every locale that has the attributes and every scope.
* Note that the attribute tags must be lower-cased in the locale of
* the registration, not in the locale of the request.
*
* @param url The ServiceURL.
* @param scopes Vector of scopes.
* @param attrTags The Vector of String
* objects specifying the attribute tags of
* the attributes to delete.
* @param locale Locale of the request.
* @exception ServiceLocationException Thrown if the
* ServiceStore does not contain the URL or if any
* error occurs during the operation or if the table
* requires a network connection that failed. This
* includes timeout failures.
*/
synchronized public void
throws ServiceLocationException {
// Get the scope level from urlScopeLangTable.
// Error if no old record to update.
if (scopeLevel == null) {
throw
"ssim_no_rec",
}
// Check existing records to be sure that the scopes
// match. Attributes must be the same across
// scopes.
// Create attribute patterns for the default locale. This
// is an optimization. Only Turkish differs in lower
// case from the default. If there are any other exceptions,
// we need to move this into the loop.
// Look through the language table for this language at scope level.
"ssim_empty_scope_table",
boolean foundIt = false;
while (en.hasMoreElements()) {
"ssim_empty_lang_table",
// Find the list of records for this language.
continue;
}
foundIt = true;
// If we've done this one already, go on.
continue;
}
// Delete old registration.
// Delete attributes from this record.
// If the locale is Turkish, then use the Turkish patterns.
} else {
}
// Reregister the record.
}
// If no record found, report error.
if (!foundIt) {
throw
"ssim_no_rec_locale",
}
}
/**
* Return a Vector of String containing the service types for this
* scope and naming authority. If there are none, an empty vector is
* returned.
*
* @param namingAuthority The namingAuthority, or "*" if for all.
* @param scopes The scope names.
* @return A Vector of String objects that are the type names, or
* an empty vector if there are none.
* @exception ServiceLocationException Thrown if any
* error occurs during the operation or if the table
* requires a network connection that failed. This
* includes timeout failures.
*/
synchronized public Vector
throws ServiceLocationException {
// Get all the keys in the table, look for scope.
while (keys.hasMoreElements()) {
// Check whether this is an abstract type entry.
// If so, then we ignore it, because we only
// want full type names in the return.
if (isAbstractTypeRecord(sstKey)) {
continue;
}
// If the scope matches then check the naming authority.
// If not already there, see if we should add this one to the
// vector.
// If wildcard, then simply add it to the vector.
if (isWildCard) {
} else {
// Check naming authority.
}
}
}
}
}
return ret;
}
/**
* Return a Hashtable with the key FS_SERVICES matched to the
* hashtable of ServiceURL objects as key and a vector
* of their scopes as value, and the key FS_SIGTABLE
* matched to a hashtable with ServiceURL objects as key
* and the auth block Hashtable for the URL (if any) for value. The
* returned service URLs will match the service type, scope, query,
* and locale. If there are no signatures, the FS_SIGTABLE
* key returns null. If there are no
* registrations in any locale, FS_SERVICES is bound to an
* empty table.
*
* @param serviceType The service type name.
* @param scope The scope name.
* @param query The query, with any escaped characters as yet unprocessed.
* @param locale The locale in which to lowercase query and search.
* @return A Hashtable with the key FS_SERVICES matched to the
* hashtable of ServiceURL objects as key and a vector
* of their scopes as value, and the key FS_SIGTABLE
* matched to a hashtable with ServiceURL objects as key
* and the auth block Hashtable for the URL (if any) for value.
* If there are no registrations in any locale, FS_SERVICES
* is bound to an empty table.
* @exception ServiceLocationException Thrown if a parse error occurs
* during query parsing or if any
* error occurs during the operation or if the table
* requires a network connection that failed. This
* includes timeout failures.
*/
synchronized public Hashtable
throws ServiceLocationException {
int len = 0;
// Get the services and signatures tables.
// Remove leading and trailing spaces.
// language tag and, if not, whether there are others.
// in another language, but not this one.
if (regStatus == NO_REGS_IN_LOCALE) {
throw
"ssim_lang_unsup",
} else if (regStatus == REGS_IN_LOCALE) {
// Only do query if regs exist.
for (i = 0; i < n; i++) {
// If no record for this combo of service type and
// scope, continue.
continue;
}
// Special case if the query string is empty. This
// indicates that all registrations should be returned.
if (len <= 0) {
new ParserBVCollector(scopes);
// Use the BtreeVector.getAll() method to get all
// registrations. We will end up revisiting some
// list elements because there will be ones
// for multiple attributes, but that will be
// filtered in the BVCollector.setReturn() method.
} else {
// Otherwise, use the LDAPv3 parser to evaluate.
scopes);
}
}
}
// Create return hashtable.
// Set up return hashtable.
// Put in signatures if there.
}
return ht;
}
/**
* Return a Hashtable with key FA_ATTRIBUTES matched to the
* vector of ServiceLocationAttribute objects and key FA_SIG
* matched to the auth block Hashtable for the attributes (if any)
* The attribute objects will have tags matching the tags in
* the input parameter vector. If there are no registrations in any locale,
* FA_ATTRIBUTES is an empty vector.
*
* @param url The ServiceURL for which the records should be returned.
* @param scopes The scope names for which to search.
* @param attrTags The Vector of String
* objects containing the attribute tags.
* @param locale The locale in which to lower case tags and search.
* @return A Hashtable with a vector of ServiceLocationAttribute objects
* as the key and the auth block Hashtable for the attributes
* (if any) as the value.
* If there are no registrations in any locale, FA_ATTRIBUTES
* is an empty vector.
* @exception ServiceLocationException Thrown if any
* error occurs during the operation or if the table
* requires a network connection that failed. This
* includes timeout failures. An error should be
* thrown if the tag vector is for a partial request
* and any of the scopes are protected.
*/
synchronized public Hashtable
throws ServiceLocationException {
// language and, if not, whether there are others.
// in another language, but not this one.
int regStatus =
if (regStatus == NO_REGS_IN_LOCALE) {
throw
"ssim_lang_unsup",
} else if (regStatus == REGS_IN_LOCALE) {
// Only if there are any regs at all.
// Process string tags into pattern objects. Note that, here,
// the patterns are locale specific because the locale of
// the request determines how the attribute tags are lower
// cased.
// Return attributes from the matching URL record.
// If nothing there, then simply return. The URL isn't
// registered.
if (scopeLevel != null) {
// We reuse ht here for attributes.
for (i = 0; i < n; i++) {
// If no registration in this scope, continue.
continue;
}
// Get the vector of lists.
// If no registration in this locale, continue.
continue;
}
// Get the service record.
// Once we've found *the* URL record, we can leave the loop
// because there is only one record per locale.
// Clear out the hashtable. We reuse it for the return.
// Store the return vector and the signatures, if any.
}
break;
}
}
}
// Put in the empty vector, in case there are no regs at all.
}
return ht;
}
/**
* Return a Vector of ServiceLocationAttribute objects with attribute tags
* matching the tags in the input parameter vector for all service URL's
* of the service type. If there are no registrations
* in any locale, an empty vector is returned.
*
* @param serviceType The service type name.
* @param scopes The scope names for which to search.
* @param attrTags The Vector of String
* objects containing the attribute tags.
* @param locale The locale in which to lower case tags.
* @return A Vector of ServiceLocationAttribute objects matching the query.
* If no match occurs but there are registrations
* in other locales, null is returned. If there are no registrations
* in any locale, an empty vector is returned.
* @exception ServiceLocationException Thrown if any
* error occurs during the operation or if the table
* requires a network connection that failed. This
* includes timeout failures. An error should also be
* signalled if any of the scopes are protected.
*/
synchronized public Vector
throws ServiceLocationException {
// language and, if not, whether there are others.
// in another language, but not this one.
if (regStatus == NO_REGS_IN_LOCALE) {
throw
"ssim_lang_unsup",
} else if (regStatus == REGS_IN_LOCALE) {
// Process string tags into pattern objects. Note that, here,
// the patterns are locale specific because the locale of
// the request determines how the attribute tags are lower
// cased.
// Make a collector for accessing the BtreeVector.
for (i = 0; i < n; i++) {
// If no service type and scope, go to next scope.
continue;
}
// Get BtreeVector with all attributes for searching.
// If there are no tags, then simply return everything in
// the BtreeVector.
if (len <= 0) {
} else {
// Use Btree vector to match the attribute tag patterns,
// returning matching records.
int j;
for (j = 0; j < len; j++) {
}
}
}
}
return ret;
}
/**
* Obtain the record matching the service URL and locale.
*
* @param URL The service record to match.
* @param locale The locale of the record.
* @return The ServiceRecord object, or null if none.
*/
synchronized public ServiceStore.ServiceRecord
return null;
}
// Search in all scopes.
return findExistingRecord(URL,
null,
}
/**
* Obtains service records with scopes matching from vector scopes.
* If scopes is null, then returns all records.
*
* @param scopes Vector of scopes to match.
* @return Enumeration Of ServiceRecord Objects.
*/
// Use a scope collector.
while (keys.hasMoreElements()) {
// Get all records.
}
}
/**
* Dump the service store to the log.
*
*/
synchronized public void dumpServiceStore() {
new Object[] {this});
while (keys.hasMoreElements()) {
// If the service type is abstract, then skip it. It will be
// displayed when the concrete type is.
if (regRec.isAbstract) {
continue;
}
// Get all records.
// Now write them out.
for (i = 0; i < n; i++) {
}
}
new Object[] {this});
}
//
//
// Register the record without any preliminaries. We assume that
// any old records have been removed and merged into this one,
// as necessary.
// Make one age out queue entry. It will go into
// all scopes, but that's OK.
// Go through all scopes.
for (i = 0; i < n; i++) {
// Initialize the urltable list vector for this URL.
lang,
false,
rec,
listVec);
// Add ageOut record, so that it gets deleted when
// the record does.
// If the type is an abstract type, then add
// separate records.
if (type.isAbstractType()) {
lang,
true,
rec,
listVec);
}
}
}
// Create a urlScopeLangTable record for this URL.
private Vector
// Get scope level, creating if new.
if (scopeLevel == null) {
scopeLevel = new Hashtable();
}
// Get lang level, creating if new.
}
// Check whether there's anything already there.
// Bug if so.
"ssim_url_lang_botch",
url,
scope});
// Add a new list vector, and return it.
return listVec;
}
private void
boolean isAbstract,
// If it's not there, make it.
}
// Otherwise, add record to all.
}
// Add a new record into the attr value table.
private void
// Go through the attribute list.
for (i = 0; i < n; i++) {
// If a type table record exists, use it. Otherwise,
// create a newly initialized one.
ttable = makeAttrTypeTable();
}
// Get the class of values.
// We're done, since there are no attributes to add.
continue;
} else {
}
// Get the BtreeVector.
// Insert a record for each value.
for (j = 0; j < m; j++) {
// Put the element into the deletion table.
}
}
}
// Return a newly initialized attribute type table. It will
// have a hash for each allowed type, with a new BtreeVector
// attached.
private Hashtable makeAttrTypeTable() {
return ret;
}
// Add a new record into the attrs table.
private void
// If no attributes, then add with empty string as
// the attribute tag.
if (n <= 0) {
return;
}
// Iterate through the attribute list, adding to the
// BtreeVector with attribute as the sort key.
for (i = 0; i < n; i++) {
// Save for deletion.
}
}
// Add a record to the ageOut queue.
}
// Remove the URL record from the database.
private void
// To deregister, we only need to find the Vector of List objects
// containing the places where this registration is hooked into
// lists and unhook them. Garbage collection of other structures
// is handled during insertion or in deregisterTypeLocale(),
// if there are no more registrations at all.
// Find the scope table..
// If it's not there, then maybe not registered.
if (scopeLangTable == null) {
return;
}
// For each scope, find the lang table.
for (i = 0; i < n; i++) {
continue;
}
// If the locale is non-null, then just deregister from this
// locale.
// also the number of regs table.
// Check for abstract type as well.
if (type.isAbstractType()) {
}
} else {
// Otherwise, deregister all languages.
while (en.hasMoreElements()) {
// also the number of regs table.
// Check for abstract type as well.
if (type.isAbstractType()) {
lang);
}
}
}
// If the table is empty, then remove the lang table.
}
}
// If all languages were deleted, delete the
// urlScopeLangTable record. Other GC handled in
// deleteTypeLocale().
}
}
// Deregister a single locale from the language table.
// Get the Vector containing the list of registrations.
"ssim_null_reg_vector",
// Walk down the list of registrations and unhook them from
// their respective lists.
for (i = 0; i < n; i++) {
}
// Remove the locale record.
}
// Find an existing record matching the URL by searching in all scopes.
// The record will be the same for all scopes in the same language.
// If locale is null, return any. If there are none, return null.
private ServiceRecordInMemory
// Look in urlScopeLangTable.
if (scopeLevel != null) {
// If scopes is null, then perform the search for all
// scopes in the table. Otherwise perform it for
// all scopes incoming.
} else {
}
while (en.hasMoreElements()) {
// If no langLevel table, continue searching.
continue;
}
// Use lang tag if we have it, otherwise, pick arbitrary.
} else {
}
// If none for this locale, try the next scope.
continue;
}
// Select out the record.
break;
}
}
return rec;
}
// Find attributes matching the record and place the matching attributes
// into the vector. Use the hashtable for collation.
static void
throws ServiceLocationException {
// For each attribute, go through the tag vector If an attribute
// matches, merge it into the return vector.
for (i = 0; i < n; i++) {
// All attributes match if the pattern vector is
// empty.
if (len <= 0) {
} else {
// Check each pattern against the attribute id.
int j;
for (j = 0; j < len; j++) {
}
}
}
}
// Check the attribute against the pattern. If the pattern is null,
// then match occurs. Merge the attribute into the vector
// if match.
throws ServiceLocationException {
// We save the attribute value if either
// the pattern is null or it matches the attribute id.
// Create new values vector so record copy isn't
// modified.
}
// Create new attribute so record copy isn't
// modified.
// Merge duplicate attributes into vector.
ht,
ret,
true);
}
}
// Check whether the incoming scopes are the same as existing
// scopes.
private void
short errCode)
throws ServiceLocationException {
// Drill down in the urlScopeLangTable table.
if (scopeLevel == null) {
return; // not yet registered...
}
// We need to have exactly the same scopes as in
// the registration.
boolean ok = true;
if (n != scopeLevel.size()) {
ok = false;
} else {
for (i = 0; i < n; i++) {
ok = false;
break;
}
}
}
if (!ok) {
throw
"ssim_scope_mis",
new Object[0]);
}
}
// Check whether an existing nonservice URL is registered under
// a different service type.
throws ServiceLocationException {
// Drill down in the urlScopeLangTable table.
if (scopeLevel == null) {
return; // not yet registered.
}
// Get hashtable of locale records under scopes. Any scope
// will do.
"ssim_null_lang_table",
// Get a record from any locale.
"ssim_empty_lang_table",
// Get vector of registrations.
"ssim_empty_reg_vector",
// OK, now check the registration.
throw
"ssim_st_already",
new Object[0]);
}
}
// Merge old record into new record.
throws ServiceLocationException {
// Charge up the hashtable with the new attributes.
for (i = 0; i < n; i++) {
}
// Merge in the old attributes.
for (i = 0; i < n; i++) {
}
}
// Change the attribute vector on the rec.
// Merge old scopes into new.
for (j = 0; j < m; j++) {
}
}
// Note that we don't have to merge security because there
// will never be an incremental update to a record
// in a protected scope.
// Change the scope vector on the rec.
}
// Delete attributes matching attrTags.
throws ServiceLocationException {
// For each attribute, go through the tag vector and put attributes
// that do not match the tags into the new attribute vector.
// If there are no attributes for this one, then simply return.
return;
}
for (i = 0; i < n; i++) {
boolean deleteIt = false;
int j;
// Now check the tags.
for (j = 0; j < len; j++) {
// If there's a match, mark for deletion.
deleteIt = true;
break;
}
}
if (!deleteIt) {
}
}
// Replace the attribute vector in the record.
}
// Convert a vector of attribute tag strings to attribute pattern objects.
throws ServiceLocationException {
// Takes care of findAttributes() case where no vector.
return null;
}
for (i = 0; i < n; i++) {
v.addElement(tag);
}
}
return v;
}
//
// Output of service store to log.
//
// Write record to config log file.
private void
new Object[] {
attributes});
}
new Object[] {
attrSig});
}
}
//
//
// Bump up the number of registrations for this service type, scope and
// locale.
private void
// Get any existing record.
// Insert a new one if none there.
}
// Look up locale.
// Add a new one if none there, otherwise, bump up old.
} else {
}
// Put it back.
}
// Bump down the number of registrations for this service type, scope,
// in all locales.
// Get any existing record.
// If none there, then error. But this should have been caught
// during deletion, so it's fatal.
"ssim_ssttable_botch",
new Object[] {
type,
scope});
// Get the Integer object recording the number of registrations.
"ssim_ssttable_lang_botch",
new Object[] {
lang,
type,
scope});
// Bump down by one, remove if zero.
}
// Garbage collection.
// Remove records from the scopeTypeLangTable,
// since there are no registrations left for this
} else {
// Put it back.
}
}
// Return REGS if the language is supported. Supported means that the
// there are some registrations of this service type in it or that
// there are none in any locale. Return NO_REGS if there are absolutely
// no registrations whatsoever, in any language. Return NO_REGS_IN_LOCALE
// if there are no registrations in that language but there are in
// others.
private int
// Look through scope vector.
boolean otherLangRegs = false;
boolean sameLangRegs = false;
for (i = 0; i < n; i++) {
// Get any existing record.
// If there are no regs, then check next scope.
continue;
}
// Check whether there are other language regs
// or same language regs.
otherLangRegs = true;
} else {
sameLangRegs = true;
}
}
// Return appropriate code.
if (otherLangRegs == false &&
sameLangRegs == false) {
return NO_REGS;
} else if (otherLangRegs == true &&
sameLangRegs == false) {
return NO_REGS_IN_LOCALE;
} else {
return REGS_IN_LOCALE;
}
}
//
// Hash key calculations and hash table structuring.
//
// Return a key for type and scope.
}
// Make a hash key consisting of the scope and service type.
final private String
}
// Return the key's scope.
if (idx > 0) {
}
return ret;
}
}
// Parse off the final lang.
return ret;
}
// Return true if the record is for an abstract type.
return rec.isAbstract;
}
}