CSE586 Project 2 - Part 1
Active Discovery


Introduction:

     In the first project, you implemented a naming service that used a mutlicast discovery protocol. This protocol was passive in nature, that is no discovery happens until it is requested. Several naming services could be within range of communication, all binding and unbinding objects locally but none would ever learn about objects available at one of the other naming services unless they made a request. We will change this to active system in which some announcement is made whenever objects are bound or unbound. This is the first part of the second project. The next portion will make specific use of changes we are making in this active discovery system.

* These are very small commands, and should be very easy to insert into the naming service you designed in Project 1.

The New Discovery Protocol:

     To implement an active discovery system, we need to add two simple announcement commands. NAMING-ANNOUNCE and NAMING-UNANNOUNCE. These commands are issued by a naming service as soon as an object is bound or unbound. They are not sent as a response to another packet like the NAMING-REQUEST packet. These commands will make it possible to keep a mapping of remotely bound objects up to date automatically, this mapping is described in detail after the commands are introduced.

     NAMING-ANNOUNCE contains the same information as a NAMING-RESPONSE, so it is followed by a signature, service name, host, port and key. NAMING-UNANNOUNCE is followed only by a signature and the name of service that has been unbound and is no longer available. for example,

"NAMING-ANNOUNCE,signature,SpecificService,pollux,9999,XQEWRS"
"NAMING-UNANNOUNCE,signature,SpecificService"
     In addition to the two new commands, the wildcard request ("*") will be modifed slightly. Currenty, the wildcard in a NAMING-REQUEST prompts a naming service to send a series of responses - listing all known services. The change you will be make should allow a wildcard to be used with a prefix (very much like the DOS prompt treats wilds cards)

For example, to request a list of all services:
"NAMING-REQUEST,signature,*,pollux,9999,XQEWRS"
For example, to request a list of all services that have a name starting with "ABC":
"NAMING-REQUEST,signature,ABC*,pollux,9999,XQEWRS"


You may not make changes to the format of this protocol. Variations are not acceptable.

The New Syntax:

The broadcast protocol used for discovery will be text based and use ip multicast as a trasnport. Multicast sockets can be created in Java using the MulticastSocket class. There are two example program that use MulticastSockets here. The multicast protocol we will use is quite simple, it will consist of a single request/response pair. Both the response and the request are treated as a string containing details separated by commas. (quotes represent string literals and are not part of the protocol)

announce ::= {"NAMING-ANNOUNCE" | "NAMING-UNANNOUNCE"} "," name

request  ::= "NAMING-REQUEST" ","
             signature "," {name | "*"}

response ::= "NAMING-RESPONSE" ","
             signature "," name, "," host "," port "," key

signatue ::= a unique client identifier (string)

name     ::= a remote object name (string)

host     ::= a hostname or ip (string)
port     ::= a port number (string)
key      ::= a key, that when combined with the host & port
             allows a client to access a remote object at
             that location (string)

string   ::= any sequence of characters that does not include a comma

The New Behavior:

     This sections describes the required behavior for each command. This is the behavior you will be graded on, and this is the behavoir required for the next part of the project. You should be mainting at least two mappings, one of names to locally bound objects, another of names for remotely-bound objects to information about where those objects can be found. This is the same as in the first part of the project.

  • NAMING-ANNOUNCE
    1. An object is bound locally to the name "anObject", using either Naming.bind() or Naming.rebind(). An announcement should now be sent for this object.
      NAMING-ANNOUNCE,aSignature,anObject,pollux,9999,XQEWRS
      If there is a failure with bind() or rebind() this command should not be sent.
  • NAMING-UNANNOUNCE
    1. An object is unbound locally from the name "anObject", using either Naming.unbind() or by binding a different object to that name using Naming.rebind(). The object unbound should now be unannounced.
      NAMING-UNANNOUNCE,aSignature,anObject
      If there is a failure with unbind() or rebind() this command should not be sent.
  • NAMING-REQUEST
    1. An attempt to discover a remote object, bound to the name "anObject" in another process, because Naming.lookup() was invoked and there is no object locally-bound to that name, and there is no information in your remote object mappings either. A request should now be sent.
      NAMING-REQUEST,aSignature,anObject
      After sending this request, the client should pause for a few seconds to allow some time for a response.

      When your naming service first starts it should send a request for all remotely bound objects "*".

      NAMING-REQUEST,aSignature,*
      This initializes your mapping of remote objects. Your naming-service will discover all the remote objects it didn't hear announcements for (because it wasn't started yet) as soon as it starts. From this point on, it will see ANNOUNE & UNANNOUNCE commands and will update your mappings accordingly. You no longer need to pause during lookup()s and list()s.

      An attempt to discover any remote objects, bound to a name that starts with "anObject", in another process is made because Naming.list("anObject*") was invoked. A request should now be sent.

      NAMING-REQUEST,aSignature,anObject*
  • NAMING-RESPONSE
    1. A NAMING-REQUEST for an object, bound to the name "anObject", was noticed. The local bindings should be checked, if an object has been locally-bound to that name a response should be sent. This response should contain the address and key for the marshalling service of the naming service sending this response.
      NAMING-RESPONSE,aSignature,anObject,pollux,9999,XQEWRS
      If the name does not match any locally-bound object, the naming service remains silent.

  • HANDLING NAMING-RESPONSE & NAMING-ANNOUNCE
    1. This is the recommomended approach to handling these commands when they are not issued by your naming service, but they are noticed by your naming service. When a NAMING-RESPONSE or NAMING-ANNOUNCE is noticed by a naming serivce, even though it may not have been solicited, that information should be cached. The best method is to keep a HashMap of the connection information, keyed on the name of the service mentioned in each command. How this map would be populated as commands are noticed is illustrated below.
      Abbreviated Commands:                Map Contents:
      
       N/A (initial)                       {}
      
       // First response seen
       NAMING-RESPONSE,anObject,...        { anObject      -> pollux,9999,XQEWRS }
      
       // Second response seen
       NAMING-RESPONSE,anotherObject,...   { anObject      -> pollux,9999,XQEWRS
                                             anotherObject -> pollux,9999,XQEWRS }
       // anObject is unannounced
       NAMING-UNANNOUNCE,anObject          { anotherObject -> pollux,9999,XQEWRS }
      
       // anObject is announced at a different location
       NAMING-ANNOUNCE,anObject            { anotherObject -> pollux,9999,XQEWRS
                                             anObject -> hadar,4444,XQEWRS }
      
      By simply inserting this information into a map, you can easily keep your local cache up to date. When Naming.lookup() is invoked, check the local bindings first, if that fails, check the cache - if that successed use the information there to connect to marshalling service and get the remote object reference.

      DO NOT establish connections to every object you see but cache that information instead, since that wastes alot of resources.

    Checklist:

  • Naming loaded:
      NAMING-REQUEST for "*" sent once.
  • Naming.lookup():
      Check local bindings first. Failing that, check your remote mapping (which is kept up to date by the two new commands). If that also fails then issue the a NAMING-REQUEST, make the client wait a few seconds for the response, then check the mapping again. When you find the object either locally-bound or you find information for that object in the remote mappings, no delay is needed.
  • Naming.bind():
      Bind a given object to a given name in your mapping of local bindings. Send a NAMING-ANNOUNCE.
  • Naming.rebind():
      If a mapping is present in your local bindings, remove the mapping for the given name and send NAMING-UNANNOUNCE. Bind a given object to a given name in your mapping of local bindings.
  • Naming.unbind():
      If a mapping is present in your local bindings, remove the mapping for the given name and send NAMING-UNANNOUNCE.
  • Naming.list():
      Merge all the locally-bound names and all the names in your remote mapping into a single array and return it. No delay is neccessary (your remote mapping is kept up to date by the two new commands).
  • The Next Part:

    The unsolicited NAMING-ANNOUNCE and NAMING-UNANNOUNCE commands keep the information a naming service has about remote object fresh. The removes a great deal of the delay between each request. Next, we will create a distribution service that distributes a work load over another group or services class servants. These servants are discovered using our protocol. They can be start started and stopped freely, with out having to perform any extra coordination with the distribution- that problem is abstracted away by the discovery protocol.

    Grading Guideline:

         This part of the project is worth 25% of the whole project. However, you should keep in mind that this part of the project will be used in the next; so it is to your advantage to start and complete this early and correctly. Grading is based on the completeness (each command should be implemented) and correctness (each command should behave as described) of each command in the protocol.

    There will NO extensions for this assignment. Late submissions will earn ZERO points.

    Requirements:

         A skeleton project is provided with that will help you organize your code. You must use this format for the project. It requires all implementation code to placed into one package and all test and demo programs to be placed in another package. The Makefile is taken care of and all you'll need to do is to place your code in the correct places.

    PART 2