Skip to content

Commit

Permalink
Externalize TreeMap in B+Trees to fix bug in Infinispan State Transfer
Browse files Browse the repository at this point in the history
  * When storing DomainObjects we need to ensure that they are correctly
    de-serialized.  Otherwise the folowing case occurs: In Infinispan backend
    we were storing TreeMaps (in B+Trees nodes) directly as Infinispan's cache
    values).  Given that the TreeMaps were Serializable, they were being
    correctly sent to other nodes by Infinispan's state transfer mechanism.
    E.g. when a new node is created and FenixFramework's auto-initialization
    process occurs, the new cache will receive the updates.  When some updated
    entries hold a reference to a Domain Object (as is the case with TreeMaps
    in B+Trees nodes), they will be deserialized by invoking
    FenixFramework.getDomainObject().  However, this invocation occurs in the
    context of an initialization of the FenixFramework class, that is still
    running the static initializer's code.  Because of this the classloader is
    still holding a lock that prevents the other thread from executing
    FenixFramework.getDomainObject.  The solution for this problem is to
    serialize/deserialize the TreeMap when they are being stored in the node's
    slot.

    NOTE: Should a programmer decide to create a DML valueType that can
    internally hold a DomainObject, the programmer is responsible for deciding
    how to store such value-type.  The safest way (at least for Infinispan) is
    to serialize/deserialize that DomainObject when setting/getting it , so
    that it doesn't get stored directly, but serialized instead.
  • Loading branch information
smmf committed Nov 21, 2012
1 parent 7f94390 commit e6d28b9
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 113 deletions.
Expand Up @@ -66,13 +66,38 @@ AbstractNode getRoot() {
abstract int shallowSize();
abstract Iterator<? extends Comparable> keysIterator();

public static Serializable externalizeTreeMap(TreeMap treeMap) {
return treeMap;
/*
* We need to ensure that no DomainObjects escape in the serialization. This would be a problem
* if 'someone' (e.g. Infinispan in clustered mode) needed to internalize a D.O. (hidden in a
* treemap entry) while the FenixFramework was still running its static initialization code. So
* we convert the TreeMap to/from a byte[] every time it is externalized/internalize by the FF.
* We wrap it in a Serializable class (TreeMapExternalization) ,because some backends (e.g. OGM)
* don't deal well with byte[] yet.
*/

public static Serializable /*byte[]*/ externalizeTreeMap(TreeMap treeMap) {
// return Externalization.externalizeObject(new TreeMapExternalization(treeMap));
return new TreeMapExternalization(treeMap);
// return treeMap;
}

public static TreeMap internalizeTreeMap(Serializable externalizedTreeMap) {
return (TreeMap)externalizedTreeMap;
public static TreeMap internalizeTreeMap(Serializable/*byte[]*/ externalizedTreeMap) {
// TreeMapExternalization treeMapExternalization = Externalization.internalizeObject(externalizedTreeMap);
return ((TreeMapExternalization)externalizedTreeMap).toTreeMap();
// return (TreeMap)externalizedTreeMap;
}

private static class TreeMapExternalization implements Serializable {
private static final long serialVersionUID = 1L;

private byte[] serializedTreeMap;

TreeMapExternalization(TreeMap<Comparable,? extends Serializable> treeMap) {
this.serializedTreeMap = Externalization.externalizeSerializable(treeMap);
}

TreeMap toTreeMap() {
return (TreeMap)Externalization.internalizeSerializable(serializedTreeMap);
}
}
}
Expand Up @@ -64,13 +64,14 @@ AbstractNode getRoot() {

public static Serializable /*byte[]*/ externalizeTreeMap(TreeMap treeMap) {
// return Externalization.externalizeObject(new TreeMapExternalization(treeMap));
return treeMap;
return new TreeMapExternalization(treeMap);
// return treeMap;
}

public static TreeMap internalizeTreeMap(Serializable/*byte[]*/ externalizedTreeMap) {
// TreeMapExternalization treeMapExternalization = Externalization.internalizeObject(externalizedTreeMap);
// return treeMapExternalization.toTreeMap();
return (TreeMap)externalizedTreeMap;
return ((TreeMapExternalization)externalizedTreeMap).toTreeMap();
// return (TreeMap)externalizedTreeMap;
}

private static class TreeMapExternalization implements Serializable {
Expand Down

0 comments on commit e6d28b9

Please sign in to comment.