All stand-alone managed objects are uniquely identifiable (addressable) through out the distributed simulation. Each object is assigned an unique number called ObjectId. The ObjectId of an object never changes and does not depend on the object's current location.
Once a new managed object is created, the Core assigns an unique ObjectId to the object. Because managed objects can and often will be created on more than one node in the same time, the Core provides mechanism to prevent assigning the same ObjectId to two or more objects.
Each node assigns new ObjectIds from its own pool of unused ObjectIds. The pool is managed by the Core's internal object ObjectProvider. Once a new object is created, the Core asks the ObjectProvider to generate a new ObjectId for the newly created object. Because each node has its own ObjectProvider and identification of the ObjectProvider is encoded in the ObjectId itself, it is ensured that two objects created on different nodes will never be assigned same ObjectId.
ObjectProviders are identifiable through their ProviderIds. The ProviderId is encoded in all ObjectIds generated by the corresponding provider.
ObjectId consists of two parts. The first part is mandatory, the second part is optional.
The mandatory part of ObjectId contains information that is needed to properly localize the object in the distributed simulation. The mandatory part uniquely identifies the object and there can't be two or more objects with the same mandatory part.
The mandatory part consists of ObjectProvider identification, ObjectProvider relative number and tracked-by-provider flag.
The ObjectProvider identification is ProviderId of the ObjectProvider which generated the ObjectId.
The ObjectProvider relative number is a number which identities the object in the provider's pool.
tracked-by-provider is one-bit flag which specifies whether the object is tracked by the object provider. Objects with this flag set can be found in the distributed simulation more quickly than other objects because the object provider monitors which node the objects resides on. Why not mark all objects tracked? The reason is that all tracked objects increase network communication among the nodes whenever the objects migrate. Also because the object providers store additional information on which nodes the objects are located, memory requirements of the providers increase as well.
The optional part of ObjectId is also called ObjectInfo because it contains additional information about the object.
What the “optional” word means? It means that even if you omit the ObjectInfo part of the ObjectId, you can still address the object in the simulation by the truncated ObjectId.
The ObjectInfo consists of ClassTypeId and archivable flag. The ClassTypeId is identification of the object's class and specifies the object's dynamic type. The archivable flag specifies whether the object is archivable or not.
Since the Massiv supports class kinds and separate compilation, the optional part may not be interpreted by all nodes properly (node does not understand type information of an alien class, for example). If such node can not interpret the additional information it either discards/truncates it or leaves it uninterpreted.
ObjectIds are never recycled. Even if an object is destroyed, the Core will never assign its ObjectId to another object. One ObjectProvider can generate about four billions of object identifications so one doesn't need to worry whether the pool can get exhausted. Anyway if this would become an issue, the Core supports two or more ObjectProviders owned by one node.
The Core uses sophisticated methods how to find an object in the distributed simulation as quickly as possible. The searching for objects is used mostly for migrations when an object is migrated to another object (see Chapter 6, Migration for more information). In such case the latter object must be found somehow in the simulation.
You don't need to know how exactly the searching algorithms internally work. The important is that it is ensured that if the object exists somewhere in the simulation, it will be found.
To find an object, the Core uses several localization methods:
First of all, each node maintains a cache of recent migrations. The cache tells for an object that migrated from the node some time ago, on which node the object is probably located. The Core supports automatic corrections of the cache if the data in it are not valid any more. When an object is found and the content of the cache is not correct for the object, the cache is automatically updated.
Each ObjectProvider maintains a cache of its tracked objects. Each tracked object notifies its ObjectProvider when it migrates so the ObjectProvider knowns where the object should be located.
If the object is found neither in the former nor the latter cache, the Core performs global search to find the object. During global search the node contacts all other nodes and asks for the object. The Core must properly handle situations when the object is not on any of the nodes but is currently being transferred over the network.