PART - Pervasive Applications RunTime


Basics

PART is a light-weight Java library for building distributed applications, with a specific focus on handheld and embedded devices. An application built using PART will typically consist of a number of processes, connected via point-to-point connections, that send events to each other and share a number of distributed objects that represents some application state (see figure below). Processes may run in ordinary PCs, mobile phones, or small embedded devices, and various networking protocols may be used for communication.

session overview

PART introduces a number of Java classes that provide various functionalities to the application. All such classes have names that starts with Ip, e.g., IpEvent and IpIdentifier. Some of these classes can be instanced explicitly by the game code using the new operator, while others are created implicitly by PART, for instance to return values from methods invoked by the application code.

The PART system is accessed by the application code mainly via the class IpSystem. This class is purely static, meaning that all of its methods are static. The system class methods provide some basic services to the application e.g., event subscription and the creation of network connection.

Identifiers

PART identifiers are used to identify PART processes and objects. Identifiers are instances of the class IpIdentifier.

IpIdentifier id = new IpIdentifier();

When identifiers are created using the new operator, they are not guaranteed to be unique. This means that if a process create two such identifiers, they may or may not be unique. For instance:

IpIdentifier id1 = new IpIdentifier();
IpIdentifier id2 = new IpIdentifier();

if (id1.equals(id2)) {
    System.out.println("equal");     <= may happen
} else {
    System.out.println("not equal"); <= may also happen
}


Identifiers can be made unique using the makeUnique method:

id1.makeUnique();

If an identifier has been made unique, it will never equal another identifier unless it's a copy of itself.

IpIdentifier id3 = new IpIdentifier();
IpIdentifier id4 = new IpIdentifier();

id3.makeUnique();

if (id3.equals(id4)) {
    System.out.println("equal");     <= won‘t happen
} else {
    System.out.println("not equal"); <= will happen
}

// make a copy of id3
IpIdentifier id5 = new IpIdentifier(id3);

if (id3.equals(id5)) {
    System.out.println("equal");     <= will happen
} else {
    System.out.println("not equal"); <= won‘t happen
}


A nice aspect of unique identifers is that they are unique even if compared to identifiers created by another process. Thus, two unique identifiers create by two different PART processes will never be equal.  This is an important property, and allows PART to use IpIdentifier instances to uniquely represents the identity of processes and game objects, as we will see in later in this document.

There is also a method that can be used to create a unique identifier directly:

IpIdentifier id2 = IpIdentifier.newUniqueId();

Events

PART uses events to asynchronously notify the application about its internal state as well as incoming data from remote processes. To receive such events, the game code needs to register an event handler with the IpSystem class:

IpSystem.addEventHandler(handler);

Several event handlers can be added by calling addEventHandler multiple times. An event handler must implement the IpEventHandler interface, which specifies a single method:

public interface IpEventHandler {
    public void handleEvent(IpEvent event);
}


Whenever PART needs to notify the application about the occurrence of an event, it calls the handleEvent method of all the event handlers added via addEventHandler.

PART events comes in many shapes. The IpEvent class is the super-class of all such events. In addition, PART introduces a number of specialised event classes that derive from IpEvent. For instance, the IpNetworkEvent class represents events that can be sent over the network to remote processes. This is described more in the section about messaging.

Debug messages

PART provides an API for generating debug messages that can be printed on for instance stdout. This is supported via the debug method of the IpSystem class:

IpSystem.debug(instance, method, level, message);

The method parameters are:
  • The instance parameter is the object instance calling debug (may be null if debug is called from a static context).
  • The method is the name of the method from where debug is called.
  • The level parameter is the debug level, where 0 is the most high priority level, and the priority decreases with increasing levels
  • The message parameter is the actual debug message
For instance:

IpSystem.debug(obj, "read", 2, "Read failure");

By default, debug messages a printed on stdout. However, only those debug messages whose level is equal to or less than the global debug level will be printed. The global debug level, which is by default 0, can be set via the setDebugLevel method:

IpSystem.setDebugLevel(level);

The higher the level, the more debug messages will be printed on stdout. PART generates a lot of internal debug messages which can be made visible by increasing the global debug level.

The debug message above will cause a message similar to the one below to be printed on stdout (if the global debug level is >= 2):

11:38:31 - DEBUG(2) - MyIoClass.read – Read failure

The PART process object

PART provides a process object that represents the local game process in a network of connected PART processes. The process object can be retrieved via the getLocalProcess method of the IpSystem class:

IpProcess myProc = IpSystem.getLocalProcess();

The process object has an identifier, which can be seen as the identifier of the local PART process:

IpIdentifier myProcId = myProc.getId();

Process identifiers (or actually the identifier of the process object) are used as parameters in many PART API methods. During the lifetime of a PART process, it will typically discover the identifiers of other PART processes. For instance, if a network connection is successfully set up to a remote process,  the identifier of the remote process becomes accessible to the local process. This is described further in the section on networking and messaging.

The local process object is in fact a special kind of a distributed object. Distributed objects are intended to be used to represent application state that needs to be shared among processes. Similar to this, the process object can be used to hold state about the local process, making it available to other processes

theme by Chris M