|
Summary: The space schema can be evolved by using codebase downloading and Java extentions, or the explicit data migration process.
OverviewDeveloping software is a never ending process. There is never a final version or a last release. This means you need to deploy new versions of the application, while using a modified version of the database schema. In many cases, the deployment is done by adding space classes, or changing the structure of existing space classes – removing some field classes or changing the inheritance structure. GigaSpaces supports addition of new space classes, as well as space data migration from one schema to another. New classes can be added without interrupting the space operation. Data migration can be done using the space underlying Entry representation – the ExternalEntry. A simple migration program can transform data stored in the space from one schema to a new schema, and create it in a new space that is used by the new version of the application. The following sections describe both of these patterns. Evolving the Space Schema using InheritanceYou can evolve the space schema using codebase downloading and inheritance, by adding a new Entry class type to your application. This class can extend an existing space Entry class. Clients are able to work with the existing Entries, as well as the newly added Entry types. Example
The system does not have to shut down during the process and clients are not interrupted. Evolving the Space Schema using Data MigrationWith this pattern, a simple program should be created in order to transform a space Entry from one schema to another. The transformer application reads an Entry from the source space (the old class schema that was used), transforms it to its new schema, and writes it to a target space (the new class schema) that is used with the new version of the application. As seen in the code example below, every migrated Entry preserves its Entry UID. The Entries are read from the source space using the GSIterator, and are written into the target space using transactions and the writeMultiple operation. Below is a transformer program, that transforms a class with two attributes into a class with one attribute. To speed up the transformation process, you may implement the transformation process as IWroker, by running the transformation business logic in the source space or in the target space. The migration process can also be optimized by running multiple threads that handle the migration of different space classes in parallel. Examplepackage com.j_spaces.transformer; import java.util.ArrayList; import java.util.Collection; import net.jini.core.entry.Entry; import net.jini.core.lease.Lease; import net.jini.core.transaction.Transaction; import net.jini.core.transaction.TransactionFactory; import com.j_spaces.core.IJSpace; import com.j_spaces.core.client.ExternalEntry; import com.j_spaces.core.client.GSIterator; import com.j_spaces.core.client.LocalTransactionManager; import com.j_spaces.core.client.SpaceFinder; public class Transformer { public Transformer() { } public IJSpace sourceSpace; public IJSpace targetSpace; static String namesOld[] = { "attrib1", "attrib2" }, typesOld[] = { String.class.getName(), String.class.getName() }; static String namesNew[] = { "attrib1" }, typesNew[] = { String.class .getName() }; static String className = "com.j_spaces.test.MyClass"; public static void main(String[] args) { Transformer transformer = new Transformer(); try { transformer.sourceSpace = (IJSpace) SpaceFinder .find("rmi://localhost/./sp1"); transformer.targetSpace = (IJSpace) SpaceFinder .find("rmi://localhost/./sp2"); ExternalEntry template1 = new ExternalEntry(className, null, namesOld, typesOld); ExternalEntry template2 = new ExternalEntry(className, null, namesNew, typesNew); transformer.sourceSpace.snapshot(template1); transformer.targetSpace.snapshot(template2); } catch (Exception e) { e.printStackTrace(); System.exit(0); } transformer.tranform(); System.out.println("Transformation done!"); } void tranform() { Collection templates = new ArrayList(); try { ExternalEntry template = new ExternalEntry(className, null, namesOld, typesOld); templates.add(template); LocalTransactionManager transactionManager = (LocalTransactionManager) LocalTransactionManager .getInstance(targetSpace); GSIterator sourceIterator = new GSIterator(sourceSpace, templates, 100, true, Lease.FOREVER); int count = 0; Transaction.Created tCreated = null; Transaction txn = null; ArrayList<Entry> entries = new ArrayList<Entry>(); while (sourceIterator.hasNext()) { ExternalEntry entry = (ExternalEntry) sourceIterator.next(); Object newValues[] = new Object[1]; newValues[0] = entry.getFieldValue(0); ExternalEntry newentry = new ExternalEntry(className, newValues, namesNew, typesNew); newentry.m_UID = entry.m_UID; count++; entries.add(newentry); if (count == 100) { while (true) try { // startTX tCreated = TransactionFactory.create( transactionManager, 1000); txn = tCreated.transaction; Entry[] ents = new Entry[entries.size()]; entries.toArray(ents); targetSpace.writeMultiple(ents, txn, Lease.FOREVER); txn.commit(); System.out.println("Done writeMultiple!"); count = 0; entries.clear(); break; } catch (Exception e) { txn.abort(); e.printStackTrace(); System.out.println("try again...."); } } } } catch (Exception e) { e.printStackTrace(); } } } |
Wiki Content Tree
Your Feedback Needed!
We need your help to improve this wiki site. If you have any suggestions or corrections, write to us at techw@gigaspaces.com. Please provide a link to the wiki page you are referring to.
Add Comment