Legacy type mapping with enum corrupts storage
If legacy type mapping is applied to enumerations in a specific way the storage may get corrupted without warning. The corrupted storage is no more loadable, it throws an exception when loading:
Exception in thread "main" one.microstream.persistence.exceptions.PersistenceExceptionConsistencyObjectId: Inconsistent Object id. Registered: 1000000000000000028, passed: 1000000000000000031
at one.microstream.persistence.internal.DefaultObjectRegistry.internalValidateObjectNotYetRegistered(DefaultObjectRegistry.java:660)
at one.microstream.persistence.internal.DefaultObjectRegistry.internalAddGetCheck(DefaultObjectRegistry.java:586)
at one.microstream.persistence.internal.DefaultObjectRegistry.internalAddGet(DefaultObjectRegistry.java:668)
at one.microstream.persistence.internal.DefaultObjectRegistry.optionalRegisterObject(DefaultObjectRegistry.java:501)
at one.microstream.persistence.binary.types.BinaryLoader$Default.getEffectiveInstance(BinaryLoader.java:332)
at one.microstream.persistence.binary.types.BinaryLoader$Default.getBuildInstance(BinaryLoader.java:671)
at one.microstream.persistence.binary.types.BinaryLoader$Default.lookupObject(BinaryLoader.java:351)
at one.microstream.persistence.binary.types.Binary.collectElementsIntoArray(Binary.java:1614)
at one.microstream.persistence.binary.java.lang.BinaryHandlerNativeArrayObject.updateState(BinaryHandlerNativeArrayObject.java:134)
at one.microstream.persistence.binary.java.lang.BinaryHandlerNativeArrayObject.updateState(BinaryHandlerNativeArrayObject.java:1)
at one.microstream.persistence.binary.types.BinaryLoader$Default.buildInstances(BinaryLoader.java:479)
at one.microstream.persistence.binary.types.BinaryLoader$Default.build(BinaryLoader.java:412)
at one.microstream.persistence.binary.types.BinaryLoader$Default.get(BinaryLoader.java:857)
at one.microstream.persistence.binary.types.BinaryLoader$Default.loadRoots(BinaryLoader.java:901)
at one.microstream.storage.embedded.types.EmbeddedStorageManager$Default.loadExistingRoots(EmbeddedStorageManager.java:345)
at one.microstream.storage.embedded.types.EmbeddedStorageManager$Default.initialize(EmbeddedStorageManager.java:366)
at one.microstream.storage.embedded.types.EmbeddedStorageManager$Default.start(EmbeddedStorageManager.java:251)
at one.microstream.storage.embedded.types.EmbeddedStorageManager$Default.start(EmbeddedStorageManager.java:1)
at one.microstream.storage.embedded.types.EmbeddedStorageFoundation.start(EmbeddedStorageFoundation.java:244)
at one.microstream.storage.embedded.types.EmbeddedStorageFoundation.start(EmbeddedStorageFoundation.java:212)
at enumLegacyTypeMappings.changeOrderError.main(changeOrderError.java:20)
Here is how-to:
-
Create a simple enum with two constants like:
enum TestEnum { ONE, TWO } -
Create a new storage and store an instance of that enum.
-
Modify the enum, swap the constants:
enum TestEnum { TWO, ONE } -
Restart the storage and store the enum instance again to update it.
-
Restart the storage again and see exception above.
Step 4 is important. If the enum instance is not update the storage does not get corrupted.
how to fix this issue , use microsteam 8.0? there are some custom code to fix this issue, I see the microstream doc, but can't find the how to define the enum "If the ordinal change is intended you need to define a manual legacy type mapping!"
With Microstream 8.0 you’ll get an PersistenceExceptionTypeConsistencyEnum before an affected enum gets persisted. To enforce Microstream to accept such an ordinal change you need to supply the manual legacy type mapping that way:
- Create a csv file containing the mapping:
old new
ChangeEnum_571.MyType#VALUE1 ChangeEnum_571.MyType#VALUE1
ChangeEnum_571.MyType#VALUE2
ChangeEnum_571.MyType#VALUE3 ChangeEnum_571.MyType#VALUE3
Please note that the two columns are separated by a tab!
With that mapping the no more existing “VALUE2” will be mapped to null.
- Register that mapping file at startup:
final EmbeddedStorageManager s = EmbeddedStorage.Foundation(DIR1).setRefactoringMappingProvider(
Persistence.RefactoringMapping(Paths.get("./enumMapping.csv")))
.start();
In general, it would be advisable to not removing or reordering enum values if possible. Adding new values is ok.