Overview | Package | Class | Use | Tree | Deprecated | Index | Help
| Berkeley DB Java Edition version 3.0.12
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## com.sleepycat.persist.evolve
Class ConversionStore

    java.lang.Object
      com.sleepycat.persist.raw.RawStore
          com.sleepycat.persist.evolve.ConversionStore

    public class ConversionStore

extends RawStore

Provides access to incompatible raw data in a store for performing manual conversions. When opening a conversion store, mutations need not be configured for handling class incompatibilities and `IncompatibleClassException` will not be thrown.

Manual conversions are needed when `Mutations` are insufficient for making complex changes to a class hierarchy or entity model. When using an conversion store, an entity may be read even if its stored class definition is incompatible with the current class definition or if the old class is no longer present. Entities may be arbitrarily manipulated, converted to be compatible with current class definitions, and written back to the store.

Note that entities with incompatible classes may be read but not written. Entities written must always conform to the current class definitions.

After a conversion, in order to open the store as an `EntityStore` or `RawStore` without causing an `IncompatibleClassException`, the `deleteUnusedType` method should be called for every incompatible class. This method should be called after converting or deleting all instances of the incompatible class.

The `deleteUnusedType` method does not verify that no instances of the given type exist, since that would require traversing one or more primary indices. Instead, the caller is required to have traversed all applicable indices and converted all instance of the type. If an instance of the type still exists and is later accessed via an `EntityStore` or `RawStore`, a `DeletedClassException` will be thrown.

A entity store does not keep track of how many instances exist for a given version of a class. The only way to find old versions is to iterate through all primary indices that may contain incompatible classes and check the types and versions. The type of a stored object is returned by `RawObject.getType()`; this will either be equal to the current type (returned by `EntityModel.getRawType`) or the previously stored type (returned by `EntityModel.getAllRawTypes`). Types may be compared using the `equals` method, or the version number may be checked.

Using a Temporary Index

Conversion via a temporary index is required for performing a key conversion, since key formats may not be changed. It may also be used to avoid making a backup of the environment before performing a conversion, since the original index is not changed until the temporary index is installed, and the temporary index may be installed safely using a transaction.

For example:

     // The class name and version of the entity instances to be converted.
     //
     String className = ...;
     int classVersion = ...;

     // Open the conversion store, the current index and a temporary index.
     //
     Environment env = ...;
     ConversionStore store = new ConversionStore(env, "myStore", null);
     PrimaryIndex<Object,RawObject> oldIndex = store.getPrimaryIndex(className);
     PrimaryIndex<Object,RawObject> tempIndex = store.getTempIndex(className);

     // Copy the instances from oldIndex to tempIndex, converting all instances
     // to conform to current class definitions.  (See Converter for
     // examples of conversion techniques.)
     //
     ...

     // Using a single transaction, atomically install the new index and delete
     // the (now unused) type of the old instances.
     //
     Transaction txn = env.beginTransaction(null, null);
     store.installTempIndex(txn, tempIndex);
     store.deleteUnusedType(txn, className, classVersion);
     txn.commit();

Using this approach, complex conversions can be performed using any number of indices at once, and a single transaction can be used to atomically commit the changes.

Note that an entire index conversion could be performed in a single transaction. However, for large indices this would use unacceptable amounts of memory to hold transactional locks. Therefore, the recommended approach for converting a large index is to copy it to a temporary index, without transactions, and then use a transaction to install the index and delete the unused types.

Author:
  Mark Hayes

Constructor Summary
`ConversionStore(Environment env, String storeName, StoreConfig config)` Opens an entity store for unchecked raw data access.

Method Summary
`PrimaryIndex<Object,RawObject>` | `createTempIndex(String entityClass)` Opens a new temporary primary index for copying new data to a new index rather than updating an index in place.
`void` | `deleteUnusedType(Transaction txn, String className, int classVersion)` Removes a type for which all instances have been converted.
`void` | `installTempIndex(Transaction txn, PrimaryIndex<Object,RawObject> tempIndex)` Installs a temporary primary index as the current index.

Methods inherited from class com.sleepycat.persist.raw.RawStore
`close, getConfig, getEnvironment, getModel, getMutations, getPrimaryIndex, getSecondaryIndex, getStoreName`

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Constructor Detail

### ConversionStore

    public ConversionStore(Environment env,
                           String storeName,
                           StoreConfig config)
                    throws DatabaseException

  Opens an entity store for unchecked raw data access.

  Parameters:
    `env` - an open Berkeley DB environment.
    `storeName` - the name of the entity store within the given environment.
    `config` - the store configuration, or null to use default configuration properties.
  Throws:
    `IllegalArgumentException` - if the `Environment` is read-only or the `config ReadOnly` property is true.
    `DatabaseException`

Method Detail

### createTempIndex

    public PrimaryIndex<Object,RawObject> createTempIndex(String entityClass)
                                                   throws DatabaseException

  Opens a new temporary primary index for copying new data to a new index rather than updating an index in place. The temporary index will be initially empty.

  Entities may be copied from the current primary index to the temporary primary index, changing the key format in the process if desired. When conversion is completed successfully, `installTempIndex(com.sleepycat.je.Transaction, com.sleepycat.persist.PrimaryIndex)` should be called. If this conversion store is closed without calling `installTempIndex(com.sleepycat.je.Transaction, com.sleepycat.persist.PrimaryIndex)`, the temporary index will be deleted. If a conversion store is opened and any residual temporary indices exist, they will be deleted.

  Conversion via a temporary index is required for performing a key conversion, since key formats may not be changed. It may also be used to avoid making a backup of the environment before performing a conversion, since the original index is not changed until the temporary index is installed, and the temporary index may be installed safely using a transaction.

  Throws:
    `DatabaseException`

### installTempIndex

    public void installTempIndex(Transaction txn,
                                 PrimaryIndex<Object,RawObject> tempIndex)
                          throws DatabaseException

  Installs a temporary primary index as the current index. The current index is removed and the temporary index is renamed to the current index.

  Throws:
    `DatabaseException`

### deleteUnusedType

    public void deleteUnusedType(Transaction txn,
                                 String className,
                                 int classVersion)

  Removes a type for which all instances have been converted.

  When performing a conversion, instances of an incompatible class version may be converted to a different type or deleted entirely. This method is called to inform the store that such a type has no instances and no longer requires conversion. In addition to freeing the space taken by the unused type definition, deleting an incompatible type allows opening an `EntityStore` (or `RawStore`) without causing an `IncompatibleClassException`.

  This method does not verify that no instances of the given type exist, since that would require traversing one or more primary indices. Instead, the caller is required to have traversed all applicable indices and converted all instance of the type. If an instance of the type still exists and is later accessed via an `EntityStore` or `RawStore`, a `DeletedClassException` will be thrown.

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
| Berkeley DB Java Edition version 3.0.12
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright (c) 1996-2006 Sleepycat Software, Inc. - All rights reserved.