Home Help Center

Dynamic Ice: Using serialised Ice 3.4.2 data in Ice 3.5.0

mefostermefoster Member Mary Ellen FosterOrganization: Heriot-Watt University, EdinburghProject: ECHOES learning environment ✭✭✭
Hello all,

I have a lot of stored data from an IceStorm-using system where I serialised all of the published messages using Base64 by subscribing a "Blobject" to each IceStorm topic with the following body:
public boolean ice_invoke (byte[] inParams, ByteSeqHolder outParams, Current current) {
        logger.trace (current.operation, DatatypeConverter.printBase64Binary (inParams));
        return true;
    }

So what I now have is lots of log files from a recent experiment, all full of tuples of the form: (topic name, op name, Base64-encoded). I now need to re-publish all of that recorded IceStorm data back through the system.

Unfortunately, I've since upgraded my desktop machine to Ice 3.5, and I note in the Ice 3.5 release notes that there's a specific warning about dynamic Ice: namely, that the parameters are now "Ice Encapsulations". And indeed, when I try to do something like the following, I get an Ice.EncapsulationException:
publisher.ice_invoke(opName, Ice.OperationMode.Normal, DatatypeConverter.parseBase64Binary(str), null);

Is there any easy way to convert those Ice 3.4.2 bytes into an Ice 3.5.0 encapsulation? As an alternative, I can downgrade my desktop to Ice 3.4.2, but I'd rather not do that unless I have to.

Thanks for any suggestions,

MEF

Comments

  • mefostermefoster Member Mary Ellen FosterOrganization: Heriot-Watt University, EdinburghProject: ECHOES learning environment ✭✭✭
    p.s. -- I just did a small test, and it did work to explicitly unserialise the bytes using the appropriate stream helper class and then to use Ice.OutputStream to create a new encapsulation for use in the ice_invoke. But I'm not excited about doing that manually for every argument of every message that was published; that's what I'd hoped to avoid by saving each message as bytes in the first place. (And if I'm going to deserialise, I might as well just publish everything in the normal way in any case ...)
  • benoitbenoit Rennes, FranceAdministrators, ZeroC Staff Benoit FoucherOrganization: ZeroC, Inc.Project: Ice ZeroC Staff
    Hi,

    You just need to wrap your data within an encapsulation. An encapsulation contains the encoding version (1.0 for you, encoded on 2 bytes), the size of the data (encoded on 4 bytes, little endian) and the data. So something like the following should do the job:
    // C# 
    byte[] data = DatatypeConverter.parseBase64Binary(str);
    byte[] encaps = new byte[data.Length + 6];
    encaps[0] = 0x01;
    encaps[1] = 0x00;
    byte[] sz = BitConverter.getBytes(data.Length + 6);
    if(BitConverter.IsLittleEndian)
    {
        encaps[2] = sz[0];
        encaps[3] = sz[1];
        encaps[4] = sz[2];
        encaps[5] = sz[3];
    }
    else
    {
        encaps[2] = sz[3];
        encaps[3] = sz[2];
        encaps[4] = sz[1];
        encaps[5] = sz[0];
    }
    System.Buffer.BlockCopy(data, 0, encaps, 6, data.Length);
    publisher.ice_invoke(opName, Ice.OperationMode.Normal, encaps, null);
    

    Cheers,
    Benoit.
  • mefostermefoster Member Mary Ellen FosterOrganization: Heriot-Watt University, EdinburghProject: ECHOES learning environment ✭✭✭
    Thanks for the help! I had to modify the sample a bit -- it seems that the size is actually the first four bytes, and then the encoding is the next two? Anyway, here's my current Java implementation, which is now working great.
    byte[] bytes = DatatypeConverter.parseBase64Binary(str);
    byte[] encapsBytes = new byte[bytes.length + 6];
                        
    // First four bytes: size
    ByteBuffer bb = ByteBuffer.allocate(4);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    bb.putInt(encapsBytes.length);
    System.arraycopy(bb.array(), 0, encapsBytes, 0, 4);
                        
    // Next two bytes: encoding version (1.0)
    encapsBytes[4] = 0x01;
    encapsBytes[5] = 0x00;
                        
    // Finally, the data
    System.arraycopy(bytes, 0, encapsBytes, 6, bytes.length);
                        
    if (publisher != null) {
        publisher.ice_invoke(opName, Ice.OperationMode.Normal, encapsBytes, null);
    }
    
    Thanks again,

    MEF
  • benoitbenoit Rennes, FranceAdministrators, ZeroC Staff Benoit FoucherOrganization: ZeroC, Inc.Project: Ice ZeroC Staff
    Hi,

    Yes of course, the size is encoded first (as documented here), sorry for this oversight. I'm glad to hear it's working now.

    Cheers,
    Benoit.
Sign In or Register to comment.