Integrating user data types

Skip to end of metadata
Go to start of metadata

This section contains the following information:

This document assumes familiarity with the Coherence C++ Object Model, including advanced concepts such as specification based class definitions.

Overview

Enabling C++ clients to successfully store C++ based objects within a Coherence cluster relies on a platform-independent serialization format known as POF (Portable Object Format). POF allows value objects to be encoded into a binary stream in such a way that the platform and language origin of the object is irrelevant.

While the Coherence C++ API includes a number of POF serializable classes, custom data types require serialization support as described below.

Serialization Options

While the Coherence C++ API offers a single serialization format (POF), it offers a variety of APIs for making a class serializable. Ultimately whichever approach is used, the same binary POF format is produced. The following approaches are available for making a class serializable:

The following table lists some of the requirements and limitations of each approach.

Approach Coherence headers in data-object Requires derivation from Object Supports const data-members External serialization routine Requires zero-arg constructor
Managed<T> No No Yes Yes Yes
PortableObject Yes Yes No No Yes
PofSerializer Yes Yes Yes Yes No

All of these approaches share certain similarities:

  • you must implement serialization routines that will allow the data items to be encoded to POF
  • the data object's fields are identified via numerical indices
  • the data object class and serialization mechanism must be registered with Coherence
  • data objects used as cache keys, must support equality comparisons, and hashing

Managed<T> (free-function serialization)

For most pre-existing data object classes, the use of Managed<T> offers the easiest means of integrating with Coherence for C++.

For a non-managed class to be compatible with Managed<T> it must have the following characteristics:

  • zero parameter constructor (public or protected): CustomType::CustomType()
  • copy constructor (public or protected): CustomType::CustomType(const CustomType&)
  • equality comparison operator: bool operator==(const CustomType&, const CustomType&)
  • std::ostream output function: std::ostream& operator<<(std::ostream&, const CustomType&)
  • hash function: size_t hash_value(const CustomType&)

The following example presents a simple Address class, which has no direct knowledge of Coherence, but is suitable for use with the Managed<T> template.

In the interest of brevity, example class definitions are inlined within the declaration.

When combined with Managed<T>, this simple class definition becomes a true "managed object", and is usable by the Coherence C++ API. This definition has yet to address serialization. Serialization support is added as follows:

Note: The serialization routines must have knowledge of Coherence. They do not, however, need to be part of the class definition file. They can be placed in an independent source file, and as long as they are linked into the final application, they will take effect.

With the above pieces in place, instances of the Address class can be wrapped via Managed<T> as Managed<Address>, and supplied to the Coherence APIs:

PortableObject (self-serialization)

The PortableObject interface is supported by the Java, .NET, and C++ versions of Coherence. It is an interface similar in concept to java.io.Externalizable, which allows an object to control how it is serialized. Any class which extends from coherence::lang::Object is free to implement the coherence::io::pof::PortableObject interface to add serialization support. Note that the class must extend from Object, which then dictates its life cycle.

We can re-write the above Address example as a managed class, and implement the PortableObject interface. In doing so, we are choosing to fully embrace the Coherence object model as part of the definition of the class, for instance using coherence::lang::String rather then std::string for data members.

This managed variant of the Address does not require the use of the Managed<T> adapter and can be used directly with the Coherence API:

Serialization via PortableObject is a good choice when the application has already decided to make use of the Coherence object model for representing its data objects. One drawback to PortableObject is that it does not easily support const data members, as the readExternal method is called after construction, and needs to assign these values.

PofSerializer (external serialization)

The third serialization option is also the lowest level one. PofSerializers are classes that provide the serialization logic for other classes. For example, we will write an example AddressSerializer which can serialize a non-PortableObject version of the above managed Address class. Under the covers the prior two approaches were delegating through PofSerializers, they were just being created automatically rather then explicitly. In most cases, it will not be necessary to utilize this approach, as either the Managed<T> or PortableObject approaches will suffice. This approach is primarily of interest when you have a managed object with const data members. Consider this non-PortableObject version of a managed Address.

Note that this version uses const data members, which makes it not well-suited for PortableObject. Here we will create an external class AddressSerializer, which will be registered as being responsible for serialization of Address instances.

Usage of the Address remains unchanged:

POF Registration

In addition to being made serializable, each class must also be associated with numeric type IDs. These IDs are well-known across the cluster. Within the cluster, the ID-to-class mapping is configured via POF User Type Configuration Elements, within C++ the mapping is embedded within the class definition in the form of an ID registration, which is placed within the class's .cpp source file.

The registration technique differs slightly with each serialization approach:

  • COH_REGISTER_MANAGED_CLASS(ID, TYPE) - for use with Managed<T>
  • COH_REGISTER_PORTABLE_CLASS(ID, TYPE) - for use with PortableObject
  • COH_REGISTER_POF_SERIALIZER(ID, CLASS, SERIALIZER) - for use with PofSerializer

Example usages of these registrations can be found in above examples.

Registrations must appear only in the implementation (.cpp) files.

Need for Java classes

After completing any of the above approaches your data object will be ready to be stored within the Coherence cluster. This will allow you to perform get and put based operations with your objects. If however you wish to make use of more advanced features of Coherence, such as queries, or entry processors you will need to write some Java code. For these advanced features to work the Coherence Java based cache servers need to be able to interact with your data object, rather then simply holding onto a serialized representation of it. In order to interact with it, and access its properties, a Java version must be made available to the cache servers. The approach to making the Java version serializable over POF is quite similar to the above examples, see ${xhtml}, and ${xhtml} for details, either of which is compatible with all three of the C++ based approaches.

Performance

Both Managed<T> and PortableObject behind the scenes utilize a PofSerializer to perform serialization. Each of these approaches also adds some of its own overhead, for instance the Managed<T> approach involves the creation of a temporary version of non-managed form of the data object during deserialization. In the case of PortableObject the lack of support for const data members can have a cost as it avoids optimizations which would have been allowed for const data members. Overall the performance differences may be negligible, but if seeking to achieve the maximum possible performance, direct utilization of PofSerializer may be worth consideration.

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.