-
Hi, I tried to store Eclipse Collection's LongArrayList (https://www.eclipse.org/collections/) with Microstream, but due to it's "items" field being transient this didn't work out of the box. So what I did was to create a new class PersistableLongArrayList like this: public class PersistableLongArrayList extends LongArrayList {
static BinaryTypeHandler<PersistableLongArrayList> provideTypeHandler() {
return Binary.TypeHandler(PersistableLongArrayList.class,
Binary.Field_int(
"size",
list -> list.size,
(list, value) -> list.size = value
),
Binary.Field(
long[].class, "items",
list -> list.items,
(list, value) -> list.items = value
)
);
}
} The items field is now not null when loaded from a stored instance, however if I change the value afterwards and call storage.store(list), shutdown the db and restart it the new value is not stored, only size is stored correctly. I've added a very simple example that shows this behavior: public class SimpleTest {
private PersistableLongArrayList root;
public static void main(String[] args) {
try {
SimpleTest t = new SimpleTest();
// DB erstellen
EmbeddedStorageManager storage = t.startDB();
// modify the list
t.root.add(t.root.size() + 1);
storage.store(t.root);
// stop DB
t.stopDB(storage);
// restart DB
storage = t.startDB();
// show root element
System.out.println(t.root);
// Observed behavior: list "grows" from s.th. like this: [1] to s.th. like this [1, 0, 0, 0] after several runs (Probably only size grows and is stored correctly and therefore the fields up to "size" are printed but empty)
// Expected beahvior: list starts with [1] and grows to something like this [1, 2, 3, 4] after several runs
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.exit(0);
}
}
private EmbeddedStorageManager startDB() {
EmbeddedStorageManager storageManager = EmbeddedStorage.start();
if(storageManager.root() == null) {
PersistableLongArrayList list = new PersistableLongArrayList();
storageManager.setRoot(list);
storageManager.storeRoot();
root = list;
} else {
root = (PersistableLongArrayList)storageManager.root();
}
return storageManager;
}
private void stopDB(EmbeddedStorageManager storageManager) {
storageManager.shutdown();
}
} Probably I just misunderstood how to use the custom BinaryHandler correctly, but I have no idea what to change right now. Kind regards, |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Hello, Here is what happen in detail: Using a custom PersistenceEagerStoringFieldEvaluator and PersistenceFieldEvaluator it is possible to persist the LongArrayList directly:
Setup:
|
Beta Was this translation helpful? Give feedback.
Hello,
You found a more complex case, the thing you missed is the “lazy Storing” behavior of Microstream (https://docs.microstream.one/manual/storage/storing-data/lazy-eager-full.html).
Here is what happen in detail:
In your PersistableLongArrayList you defined a typeHandler that stores a reference to a long-Array.
During the first store microstream detects that the referenced array has not been persisted before will persist it. Subsequent stores will detect that the array has been persisted already and skip it because of the lazy storing behavior. If you add enough elements to the LongArrayList the list will internally create new and lager array. This new array will be recognized and per…