AnyInfo Example 4: Implementing a Scalable NDS Design with ConsoleOne Snap-ins
Articles and Tips: article
Senior Research Engineer
01 Aug 1998
Discusses the fourth example in the series. Shows how to extend the schema design described in the third example to be more scalable. Describes what we mean by an NDS scalability problem and the ways to solve it. Also presents the Java code necessary to implement the solutions discussed in part one.
This article discusses the fourth example in the series introduced in, "The Transformation of API_Info into AnyInfo, a Multi-Tiered, Database Application" in the July issue. In this example, we extend the schema design described in Example 3 to be more scalable.
The AnyInfo NDS Scalability Problem and Solutions
In the original design of the C-based API_Info application in Example 1 of this series, no thought was given to scalability. The NDS schema was extended for a single object type so that objects could be created to represent locations of the application's service in the network. The old API_Info client searches the tree for objects of the API_Info type in order to build a list of available services and then select the closest one. This simple design works fine in small trees, but if you have thousands of nodes, the time required for the initial tree search is enormous.
This article will present three solutions to this scalability problem. There are undoubtedly other solutions out there. If you would like to share them, please E-mail firstname.lastname@example.org.
Scalability Solution 1: Use a Single List to Reference all Needed Objects
Scalability Solution 1 is the design that is implemented in AnyInfo, the application that is the basis for this series. A description of the ConsoleOne snap-ins for this solution can be found in part two of this article.
The tree shown in Figure 1 has already been extended for AnyInfo. You can tell because the AnyInfo schema extension adder tool has been disabled while the remover tool is enabled; also there is an AnyInfoList object at the root of the tree.
Figure 1: When a tree's schema is extended for AnyInfo, an AnyInfoList is automatically instantiated at the root.
The AnyInfoList object is especially designed to manage a list of all the regular AnyInfo objects created in the tree. In Solution 1, the list object is always located in the root, so no time consuming search is required at application launch. The application simply references the list object at its known location and reads the list of entries to obtain the location of every AnyInfo object in the tree.
The maintenance of the list is completely automated, so the administrator need not be aware of its existence. When the tree is extended, the AnyInfo schema extension tool snap-in transparently creates the list object at the root of the newly extended tree (as shown in Figure 1). If the tree is unextended, the AnyInfo schema extension tool snap-in deletes the list object.
When the administrator creates an AnyInfo object (such as those displayed by ConsoleOne in Figure 2), anywhere in an AnyInfo extended tree, the AnyInfo create object snap-in adds distinguished name reference for the new object to the list (as shown in Figure 3).
Figure 2: Whenever an AnyInfo object is created, a distinguished name attribute referencing it is added to the list object at the root.
Figure 3: If an AnyInfo object is deleted, NDS will delete any distinguished name atribute which references the deleted object.
Since the list entries are of the distinguished name syntax, much of their maintenance is managed automatically by NDS. If an AnyInfo object is moved, NDS will update its entry in the list for the new location. If an AnyInfo object is deleted, NDS will delete its entry from the list, so no application intervention is required.
Scalability Solution 2: Implement a List of Lists
The downside of Scalability Solution 1 is that it has only one list object. This means the administrator cannot put lists inside of particular containers in the tree to take advantage of the container's inherited rights. If administrators could put AnyInfo lists inside of particular containers in the tree, they could implement a fine-grained security model so that access to the lists could be tailored for each specific group within their organizations.
For example, the users in a Marketing container would be able to access database list objects in the Marketing container but not necessarily those lists in the Accounting container. This would make the location of specific databases available to the people in Marketing while potentially making them unavailable to others.
Solution 2 uses two types of list objects, one to contain a list of the application's regular object instances (in our case database references called AnyInfo objects) and another list to contain a list of those lists (for simplicity we will refer to this as the "master list" as shown in Figure 4).
Figure 4: A master list can be used to implement a more articulate security model for your application.
The application still needs a known location to start with (you don't want to have to search the tree for list objects or you will have a scalability problem again.) So, this design would place the list of lists at the root. The entries in the master list could be added and managed automatically just as the AnyInfo object entries are managed in the lists described in Solution 1. However, each group would probably want their own administrator to manage their database lists. So, the supervisor would have to manage the master list object's ACL so that only the administrators had the ability to access the master list.
Also with this model, the application's group administrators would be responsible to create both the database location objects and the lists which would contain them. Although this makes administration slightly more complicated than solution 1, it eliminates a level of bureaucracy, allowing group administrators direct control of their user's database access without having to go through a central administrator.
For the sake of brevity, we decided to use Solution 1 for AnyInfo. However, if you can code Solution 1, you can code the more flexible Solution 2 and that is what we suggest that you do for your application.
Because of the increased complexity and code, we decided to use Solution 1 for AnyInfo. However, there is a third option that we thought might be useful.
Scalability Solution 3: Use Catalog Services to Obtain a List of all AnyInfo Objects
Catalog Services is relatively new to Novell. It provides exposed APIs that allow your applications to make queries to NDS much like you would make an SQL query to a database.
In the case of AnyInfo, we would make a query to Catalog Services asking for all entries in the tree of our desired class type. Catalog Services would then perform the necessary searching to build the list we need. Although this would take a while initially, Catalog Services would then dynamically maintain the list for us. As objects were created and deleted, Catalog Services would add or remove them from the list. Access to the list by an application would be instantaneous but the data might be a little old depending on how frequently Catalog Services is configured to update the list. Look for a future article on how to use Catalog Services for AnyInfo.
Implementing AnyInfo's NDS Scalability Solution
Figure 5 shows the object models for the ConsoleOne snap-ins that implement the NDS design in Scalability Solution 1. Most of the functionality in these AnyInfo snap-ins have analogs in the API_Info snap-ins described in the March through June issues of this publication.
Figure 5: Object models for AnyInfo snap-ins.
High Level Description of the AnyInfo ConsoleOne Snap-in Classes
Below are some highlights of the ConsoleOne classes shown in Figure 5.
Common. The AnyInfoCommon class is not really a snap-in. It serves as kind of a library of common methods available to any of the packages in the AnyInfo snap-in set.
The AnyInfoSchemaChangeListener interface is unique to AnyInfo. It must be implemented by any class that wishes to be notified when the schema is extended or unextended. For example, AnyInfoAddObjSnapin, the class of object which manages the creation of regular AnyInfo database location NDS objects, implements the AnyInfoSchemaChangeListener interface because it needs to know if the schema has been extended or unextended so that it can enable or disable its menu item appropriately (shown in Figure 6). If the schema is extended for AnyInfo, AnyInfoAddObj will enable its "Create AnyInfo Object" menu item. If the schema is unextended the menu item is disabled.
Figure 6: AnyInfoAddObjSnapin needs to know when the schema is extended or unextended so that it can manage its menu item.
Display Object Icon. The AnyInfoListImageSnapin and the AnyInfoRegularImageSnapin both implement the DisplayImageSnapin interface to display the appropriate images when their object types are selected in ConsoleOne.
Schema Tools. AnyInfoToolbarMenuBase inherits tool bar icon and menu item functionality from ConsoleOne's AbstractToolbarMenuSnapin and then provides it to AnyInfo's class adder and remover snap-ins. AnyInfoToolbarMenuBase is the source for schema change events. Whenever the schema is extended or unextended by the class adder or remover, it notifies its list of SchemaChangeListeners so that they can check the schema state and respond appropriately.
For example, both the class adder and remover are SchemaChangeListeners. If the adder extends the schema, the remover will want to know so it can enable the state of its menu item and tool bar icon. If the remover unextends the schema, the adder will want to know so it can enable the state of its menu item and tool bar icon.
Create Object. In addition to implementing the SchemaChangeListener interface, the AnyInfoAddObjSnapin implements ConsoleOne's MenuSnapin interface to create the menu shown in Figure 6.
AnyInfoAddObjSnapin also implements ConsoleOne's ShellListener interface so that it can receive messages about occurrences in the ConsoleOne Shell.
For example, one of the methods required by the ShellListener interface is treeSelectionChanged( ). The shell will call this method in all ShellListeners whenever the user selects a different object in the namespace view. This allows AnyInfoAddObjSnapin to check every newly selected namespace object in order to see if it can contain an AnyInfo object. If it can and the schema is extended for AnyInfo, AnyInfoAddObjSnapin will enable its add AnyInfo object menu item shown in Figure 6. If the newly selected object cannot contain an AnyInfo object, AnyInfoAddObjSnapin will disable the menu item.
Edit Property Pages. Every AnyInfo PageSnapin requires a derivation of java.awt.Panel to be a GUI for its property page in the property book.
The GUI for the regular AnyInfo object's page snap-ins are similar enough that they can inherit much of their functionality from their common base class AnyInfoAttrEditPanel. The GUI for the AnyInfoList object is simply a list displaying all of the AnyInfo objects in the tree. By implementing the AnyInfoMPECPanel interface, all of these panels can be used by the functionality in the AnyInfoEditPageBase class.
As mentioned earlier, most of the functionality in these AnyInfo snap-ins have virtually identical implementations in the API_Info snap-ins described in the March through June issues of this publication. If you would like to see the differences, you can download the AnyInfo snap-in sources and project from our download site at: http://www.novell.com/coolsolutions/author/3202.html
Note: The NDS namespace snap-ins in this download are unique in that they expose the APIs used for the source code in this article series. These APIs may never be exposed in the final released ConsoleOne product.
For more information about other examples in this series, refer to http://developer.novell.com/education/roadmap.
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.