Archived

This forum has been archived. Please start a new discussion on GitHub.

Question Re: Object Instance Identity

Hello,
I am having difficulty finding/understanding how to identify the object instance identity. Not just the remote object identity, but rather how to distinguish between two instances of the same class. From the documentation, it appears that when using Freeze to add instance persistance, an additional data member, such as a UUID, must be added so as to provide a key for search for a specific instance of an object. As an example, the documentation makes reference to a local pointer to an object address, and that address represents the local uniquie instance identity, but goes vague in the context of a remote object identity by seemingly equating the identity of an un-instanciated object, rather than the instance of a given object, so as to uniquely identify it from all other instances of the same object or class. Any help getting this concept would be most appreciated!
Thanks,
Andy

Comments

  • mes
    mes California
    Hi Andy,

    Welcome to the forum.

    This FAQ might help to clear things up for you. If not, please feel free to follow up with more specific questions.

    Regards,
    Mark
  • Question Re: Object Instance Identity

    Hello,

    Thanks for the FAQ, but I have no questions regarding the contents of the FAQ.

    Specifically, ...I am having difficulty finding/understanding how to distinguish between two instances of the same class. From the documentation, it appears that when using Freeze to add instance persistance, an additional data member, such as a UUID, must be added so as to provide a key for search for a specific instance of an object. As an example, the documentation makes reference to a local pointer to an object address, and that address represents the local uniquie instance identity, but goes vague in the context of a remote object identity by seemingly equating the identity of an un-instanciated object, rather than the instance of a given object, so as to uniquely identify it from all other instances of the same object or class.

    Thanks,
    Andy
  • mes
    mes California
    Hi,

    Are you asking about using Freeze to store instances of Slice classes (i.e., as a simple object-oriented database), or are you asking about using Freeze to store the persistent state of Ice objects?

    There is a subtle but important difference here. If you have no intention of using these instances as servants that incarnate Ice objects, then the situation is no different than with any other database: each record (or object) typically has a unique key. If none of the existing data members is a good candidate, and your application requires a way to distinguish between them, then you'll probably need to add a data member to serve that purpose.

    If instead your instances are servants, then a Freeze evictor is one way to maintain the persistent state of the Ice objects. The evictor takes care of associating the Ice object identity with each record. Whether a servant needs to know the identity of the Ice object it is incarnating is another application-specific decision. Remember that a single servant can implement any number of Ice objects, and in the context of a remote invocation a servant can discover the identity being targeted by the client via the Ice::Current argument.

    If I still haven't answered your question, perhaps you can provide a more concrete use case.

    Regards,
    Mark
  • First a clairification

    Hello,
    Thanks for your reply. Before I respond to your post, I need a clairification of meaning. In the context of servants, your meaning of "identity" is refering to object or instance of object (as in "car" or "VIN_1", "VIN_2", etc.)?
    Thanks,
    Andy
  • mes
    mes California
    We try to be careful in our terminology, so when we use the term "identity" it's usually safe to assume we are referring to the identity of an Ice object (i.e., an Ice::Identity). That's what I was referring to in my replies above.

    Regards,
    Mark
  • Clairification

    Careful is good, and I could have surmised your response. But the specific distinction I have requested clairification on is not clear to this "casual observer", given the documentation and newsletter articles (plus your FAQ reference), which prompts the inquiry. Please advise with a careful and specific reply.
    Thanks,
    Andy
  • bernard
    bernard Jupiter, FL
    Hi Andy
    I am having difficulty finding/understanding how to identify the object instance identity. Not just the remote object identity, but rather how to distinguish between two instances of the same class.

    An Ice object (remote Ice object if you like) has always an identity: if you have a proxy to this object, you can call ice_getIdentity() on this proxy to get this identity (it's a local call).

    Local class instances don't have a special identity. If we take the following Slice class:
    // Slice
    class Node
    {
    string name;
    string address;
    Node next; // pass-by-value with "pointer" semantics
    };

    Ice does not generate an additional "identity" member in the C++ or Java class named Node.

    Now, say you pass a set of Nodes through an Ice operation, such as:

    void sendNodes(Node root);

    Ice will only pass a single copy of each Node instance, to be able to recreate an identical structure in the receiver. To do so, Ice needs to determine whether two nodes are the same or not, and this done by comparing Node pointers in C++, or Node object references in Java.

    I hope this is clearer now!

    Best regards,
    Bernard
  • Clairification of "Identity"

    "To do so, Ice needs to determine whether two nodes are the same or not, and this done by comparing Node pointers in C++, or Node object references in Java."

    Implies that "Ice::Identity" refers to "object" rather than "instance of object",
    Implies that your are refering to an ICE internal process,
    Implies that a method is supplied by the developer to enable the comparison?

    Thanks, Andy
  • bernard
    bernard Jupiter, FL
    Hi Andy,
    Implies that "Ice::Identity" refers to "object" rather than "instance of object",

    As described in the FAQ entry Mark referenced earlier, an Ice object is an abstract concept. Each Ice object has an identity. Instances of various classes generated by Ice (for Slice classes, structs, exceptions, sequences ...) don't have an associated Ice identity.

    I don't see what you mean by distinguishing 'object' and 'object instance': they are typically synonymous.
    Implies that your are refering to an ICE internal process,

    Marshalling and unmarshalling operation parameters is indeed an internal Ice process.
    Implies that a method is supplied by the developer to enable the comparison?

    No, it is straight pointer or object reference comparison: Ice does not generate a special operator== (C++) or equals method (Java), and does not expect the application to define such function or method.

    Best regards,
    Bernard
  • Another way of putting this...

    If you have a Slice class instance and compare it with a another Slice class instance, they have the same identity if their references or pointers point at the same physical hunk of memory. That is, equality is determined as an identity comparison, not a value comparison. In particular, if you have two Slice class instances with the same member values, they compare different even if the members all have identical values:
    // Slice
    class Foo { int x; };
    
    // Java
    Foo f1 = new Foo();
    f1.x = 5;
    Foo f2 = f1; // f1 and f2 denote the same class instance, so they are equal
    

    Compare with:
    // Java
    Foo f1 = new Foo();
    f1.x = 5;
    Foo f2 = new Foo();
    f2.x = 5; // f1 denote different class instances, so they are not equal
    

    This illustrates what is meant by identity comparison: the identity of the class instances is their address in memory.

    For servants, the situation is different. Each servant responds to requests targeted at specific Ice object identities. The identity is embedded in proxies. So, two proxies point at the same Ice object if they embed the same Ice object identity.

    Cheers,

    Michi.
  • Clairification of "Identity"

    Michi & Bernard,

    First, I appreciate your replys.

    To use the demo/freeze/phonebook as a use case:

    "PhoneBookI::createContact(const Ice::Current& c)" uses a UUID to create an "identity" which is subsequently embedded into the proxy returned to the caller. This is not a pointer address, but yet is a slice class instance.

    Please advise how this fits into both of your explainations.

    Thanks,
    Andy
  • bernard
    bernard Jupiter, FL
    Hi Andy,

    Here is the code in question:
    PhoneBookI::createContact(const Ice::Current& c)
    {
        //
        // Get a new unique identity.
        //
        Ice::Identity ident;
        ident.name = IceUtil::generateUUID();
        ident.category = "contact";
    
        //
        // Create a new Contact Servant.
        //
        ContactIPtr contact = new ContactI(_contactFactory);
        
        //
        // Create a new Ice Object in the evictor, using the new identity
        // and the new Servant.
        //
        _evictor->add(contact, ident);
    
        
        //
        // Turn the identity into a Proxy and return the Proxy to the
        // caller.
        //
        return IdentityToContact(c.adapter)(ident);
    }
    

    _evictor here is a Freeze evictor, so the identity/servant pairs inserted into this evictor are stored persistently in a Berkeley DB database

    The contact object is a servant, and has no identity. In this context, this servant (a class instance) is not compared for equality with any other object.

    The application decides that this servant will incarnate an Ice object with contact/UUID as identity--this association occurs here:
     _evictor->add(contact, ident);
    

    With this call, the abstract Ice object whose identity is ident is incarnated by contact. This call does not change contact (except contact's reference count); it just ensures that requests to "ident" delivered to _evictor's object adapter are dispatched onto contact.

    Is anything still unclear?

    Best regards,
    Bernard
  • Bernard: The phonebook use case was intended to facilitate a distinction in light of yours and Michi's prior explaintions, not an absence of understanding what the code is doing.

    From Michi:"If you have a Slice class instance and compare it with a another Slice class instance, they have the same identity if their references or pointers point at the same physical hunk of memory. That is, equality is determined as an identity comparison (this appears inconsistant w/ the previous sentence), not a value comparison. In particular, if you have two Slice class instances with the same member values, they compare different even if the members all have identical values (due to different address?)...This illustrates what is meant by identity comparison: the identity of the class instances is their address in memory.
    For servants, the situation is different."

    From Bernard:"The contact object is a servant, and has no identity. In this context, this servant (a <slice> class instance) is not compared for equality with any other object." (this appears inconsistant w/ Michi's explaination)

    It appears that the fact that a class instance is a slice class instance, is not the only distinction. But in the case of use in Freeze evictors, the identity must be supplied by the developer and embedded into the proxy, which allows ICE to perform a find from the database?

    Attempting to bring the issue into focus: When is a slice class instance identity defined by a unique pointer address, and when must the developer provide a unique identifier?

    Thanks,
    Andy
  • I get the impression that the confusion revolves around the distinction among Slice classes, servants, and Ice objects.

    A Slice class is a value, much like a struct, except that Slice classes support a few things that structures don't. In particular, classes can have operations and support inheritance, whereas Slice structs do not.

    The identity of a Slice class is its unique location in memory. Two class instances in an address space have different identities, regardless whether their members have the same values or not. This is just like the C++ object model, where the location in memory of a C++ class instance is its identity.

    A servant is a programming-language construct that incarnates an Ice object. A Slice class instance can be a servant. However, you need not use a Slice class as a servant--you can also use a programming-language class instance that derives from the generated skeleton for a Slice interface.

    A servant is what responds to invocations from clients. Clients invoke operations via proxies. A proxy, in turn, is a handle much like a C++ pointer or Java reference, except that a proxy can denote things in another address space. A proxy contains two fundamental items of information:
    • addressing information that provides the host and port at which the server runs.
    • an Ice object identity

    The addressing information tells the client-side run time where it can find the server, and the object identity tells the server which of the possibly many Ice objects hosted at the server's endpoint the request is for.

    In other words, the addressing information identifies the server process and, implicity, the object adapter within the server, and the Ice object identity identifies which particular target object that is hosted by the adapter will handle the request.

    When the client sends a request, it opens a connection to the endpoint at which the server runs. With the request, the client sends the Ice object identity that is embedded in the proxy, the name of the operation to call, and the in-parameters for the operation, if any.

    When the server receives the request, it implicitly knows which object adapter the request is targeted at because no two adapters can listen for incoming requests on the same port. The server-side run time retrieves the Ice object identity for the request and uses it as the key for a lookup in the adapter's ASM (active servant map). The ASM is a lookup table that uses the Ice object identity as the key, and the servant identity as the lookup value.

    In other words, in C++, the ASM stores the Ice object identity (which is a pair of strings) and the lookup value is a C++ pointer to the servant instance for that Ice object identity. In Java, the lookup value is a Java reference instead.

    So, what the ASM provides is the link between the Ice object identity in the proxy and the programming-language class instance that incarnates the corresponding Ice object. Or to put it differently, the ASM stores pairs of Ice object identity and class identity. (The pointer or reference that is the lookup value is the identity of the corresponding servant.)

    Often, a servant is simply a programming-language construct that has nothing to do with a Slice class. But, a Slice class can be used as a servant: instantiate a Slice class and add it to the ASM as a servant. Now the client can invoke operations on the class instance in the server, provided it has a proxy that contains the Ice object identity that, in the server's ASM, points at that class instance.

    So, there are two identities involved here: the Ice object identity, which identifies the abstract and conceptual Ice object, and the servant identity (or Slice class identity), which identifies a particular object instance within the server's address space.

    The mapping between Ice object identity and servants need not be one-to-one. You can register the same servant instance multiple times in the ASM, using a different Ice object identity each time. In that case, a single servant instance incarnates more than one Ice object.

    You can read about this in detail in the Ice manual. Check out the intro section that explains the basic concepts, and look at the advanced server chapter and the life cycle chapter. They explain all this in great detail.

    Cheers,

    Michi.