Archived

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

Ice class instance persistence

Given a very basic slice class definition, say:
module test {
    class CountryDefinition {
        string Description;
    };
};

I may have large number of CountryDefinition objects in memory and my server will serve those instances up to a client. In place of a database I'm simply interested in persisting these instances to disk for durable storage. My current language of choice is C# and I'd love to be able to simply use traditional serialization techniques to serialization a collection of them, however this is not possible because of the inheritance from Ice.ObjectImpl.

I am imagining that using the Object's Helper class and the Ice.InputStream and Ice.OutputStream classes this is possible, I'm just struggling to find a working example to base it off of. If this is indeed the correct approach, Is there an example of using a file as the source/destination for the Ice Stream objects? If it's not, can you provide some guidance on serializing collections of slice classes to disk?

Thank you-
Rick Spurgeon

Comments

  • mes
    mes California
    Hi Rick,

    We'll probably do something about the ObjectImpl inheritance issue in the next Ice release.

    Meanwhile, it's pretty easy to serialize one or more Ice objects. The basic idea is that you create an OutputStream, write your data, then call finished on the stream to obtain a byte array representing the data in the Ice encoding. You can then write this byte array to a file, stash it in a database, etc.

    You said you want to write a "collection" of objects, so let's assume you have a sequence:
    // C#
    test.CountryDefinition cd1 = ..., cd2 = ...;
    Ice.Object[] arr = { cd1, cd2 };
    Ice.OutputStream os = Ice.Util.createOutputStream(communicator);
    os.startEncapsulation(Ice.Util.Encoding_1_1, Ice.FormatType.SlicedFormat);
    Ice.ObjectSeq.write(os, arr);
    os.writePendingObjects(); // Not necessary to call this when using the 1.1 encoding
    os.endEncapsulation();
    byte[] bytes = os.finished();
    // write bytes to file...
    
    A couple things I should mention here. First, I'm wrapping the objects in an "encapsulation". This isn't strictly necessary but it's not a bad idea if the data is going to be retained for a significant length of time because it embeds the encoding version, although it does add a little overhead to the encoded data. Notice also that the encapsulation specifies a format. I've used the sliced format here, which is more flexible but adds additional overhead to the encoding. To minimize the encoded size, you can use CompactFormat instead. If you're sure that the application will know all of the possible class types that might be present in the encoded data, using CompactFormat is a reasonable choice. You can read more about formats on this page.

    Second, I stored the objects in an array of Ice.Object. This was just for simplicity, since Ice already defines Ice.ObjectSeq. If you define your own sequence type, make sure you add the --stream option when running the Slice compiler so that it generates the necessary streaming code for the public stream API.

    Finally, for the sake of completeness I included a call to writePendingObjects, although it's not necessary to call this method when using the 1.1 encoding.

    To later decode the data, you can do the following:
    byte[] data = ...; // Get the encoded data from somewhere
    Ice.InputStream input = Ice.Util.createInputStream(communicator, data);
    Ice.EncodingVersion ver = input.startEncapsulation();
    Debug.Assert(ver.Equals(Ice.Util.Encoding_1_1)); // Sanity check
    Ice.Object[] arr = Ice.ObjectSeq.read(input);
    input.endEncapsulation();
    
    foreach(Ice.Object obj in arr)
    {
        test.CountryDefinition cd = (test.CountryDefinition)obj;
        ...
    }
    
    The disadvantage of using Ice.ObjectSeq here is that you'll have to downcast each of the elements in the array to a more-derived type.

    Hope that helps,
    Mark
  • Mark-

    Thank you for the reply, this worked out well. Helpful as always.

    Rick