diff options
author | Eike Stepper | 2013-03-09 09:21:12 +0000 |
---|---|---|
committer | Eike Stepper | 2013-03-09 11:59:26 +0000 |
commit | f08335da87834546e311c8d7240edc63c39afa2e (patch) | |
tree | 352c5f06d7f34abfc7d69d11b6ff2bfbbc181a4f | |
parent | 5bc362a99567e233660fdffbd512a6f1b973ad1b (diff) | |
download | cdo-f08335da87834546e311c8d7240edc63c39afa2e.tar.gz cdo-f08335da87834546e311c8d7240edc63c39afa2e.tar.xz cdo-f08335da87834546e311c8d7240edc63c39afa2e.zip |
[401763] Make CDO Server more robust against data dictionary changes
https://bugs.eclipse.org/bugs/show_bug.cgi?id=401763
11 files changed, 227 insertions, 50 deletions
diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java index f115dc24a0..928180ccea 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBDatabase.java @@ -13,8 +13,10 @@ package org.eclipse.net4j.db; import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBSchemaElement; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; import org.eclipse.net4j.util.collection.Closeable; import org.eclipse.net4j.util.container.IContainer; +import org.eclipse.net4j.util.event.IEvent; /** * @author Eike Stepper @@ -36,6 +38,13 @@ public interface IDBDatabase extends IContainer<IDBTransaction>, Closeable public IDBSchemaTransaction getSchemaTransaction(); + public void ensureSchemaElement(RunnableWithSchema updateRunnable, RunnableWithSchema commitRunnable); + + public <T extends IDBSchemaElement, P extends IDBSchemaElement> T ensureSchemaElement(P parent, Class<T> type, + String name, RunnableWithSchemaElement<T, P> runnable); + + public IDBTable ensureTable(String name, RunnableWithTable runnable); + public IDBTransaction openTransaction(); public IDBTransaction[] getTransactions(); @@ -44,10 +53,23 @@ public interface IDBDatabase extends IContainer<IDBTransaction>, Closeable public void setStatementCacheCapacity(int statementCacheCapacity); - public <T extends IDBSchemaElement, P extends IDBSchemaElement> T ensureSchemaElement(P parent, Class<T> type, - String name, RunnableWithSchemaElement<T, P> runnable); + /** + * @author Eike Stepper + */ + public interface SchemaChangedEvent extends IEvent + { + public IDBDatabase getSource(); - public IDBTable ensureTable(String name, RunnableWithTable runnable); + public IDBSchemaDelta getSchemaDelta(); + } + + /** + * @author Eike Stepper + */ + public interface RunnableWithSchema + { + public void run(IDBSchema schema); + } /** * @author Eike Stepper diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java index 00fdd6003a..8f40730e75 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java @@ -10,7 +10,6 @@ */ package org.eclipse.net4j.db.ddl; - /** * An index specification in a {@link IDBTable DB table}. * @@ -50,6 +49,11 @@ public interface IDBIndex extends IDBSchemaElement /** * @since 4.2 */ + public IDBIndexField getIndexFieldSafe(String name) throws SchemaElementNotFoundException; + + /** + * @since 4.2 + */ public IDBIndexField getIndexField(String name); /** @@ -60,6 +64,11 @@ public interface IDBIndex extends IDBSchemaElement /** * @since 4.2 */ + public IDBField getFieldSafe(String name) throws SchemaElementNotFoundException; + + /** + * @since 4.2 + */ public IDBField getField(String name); public IDBField getField(int position); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java index 39eda29ca8..a1e16a4728 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java @@ -48,6 +48,11 @@ public interface IDBSchema extends IDBSchemaElement */ public IDBTable removeTable(String name) throws DBException; + /** + * @since 4.2 + */ + public IDBTable getTableSafe(String name) throws SchemaElementNotFoundException; + public IDBTable getTable(String name); public IDBTable[] getTables(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java index d7af67b16c..d953725a03 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java @@ -38,6 +38,11 @@ public interface IDBTable extends IDBSchemaElement public IDBField addField(String name, DBType type, int precision, int scale, boolean notNull); + /** + * @since 4.2 + */ + public IDBField getFieldSafe(String name) throws SchemaElementNotFoundException; + public IDBField getField(String name); public IDBField getField(int position); @@ -81,6 +86,11 @@ public interface IDBTable extends IDBSchemaElement /** * @since 4.2 */ + public IDBIndex getIndexSafe(String name) throws SchemaElementNotFoundException; + + /** + * @since 4.2 + */ public IDBIndex getIndex(String name); /** diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/SchemaElementNotFoundException.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/SchemaElementNotFoundException.java index e663db898f..d807be831c 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/SchemaElementNotFoundException.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/SchemaElementNotFoundException.java @@ -11,7 +11,7 @@ package org.eclipse.net4j.db.ddl; import org.eclipse.net4j.db.DBException; -import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.spi.db.DBSchemaElement; /** * @since 4.2 @@ -29,10 +29,11 @@ public class SchemaElementNotFoundException extends DBException public SchemaElementNotFoundException(IDBSchemaElement parent, IDBSchemaElement.SchemaElementType type, String name) { - super("Schema element '" + name + "' of type " + type + " not found in " + DBUtil.dumpToString(parent)); + super(type.toString() + " " + DBSchemaElement.name(name) + " not found in " + parent.getSchemaElementType() + " " + + parent); this.parent = parent; this.type = type; - this.name = name; + this.name = DBSchemaElement.name(name); } public IDBSchemaElement getParent() diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java index 9a3178e28b..eb61cc3dea 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java @@ -18,10 +18,15 @@ import org.eclipse.net4j.db.IDBTransaction; import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBSchemaElement; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; +import org.eclipse.net4j.internal.db.ddl.delta.DBSchemaDelta; import org.eclipse.net4j.spi.db.DBAdapter; import org.eclipse.net4j.spi.db.DBSchema; import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.container.SetContainer; +import org.eclipse.net4j.util.event.Event; +import org.eclipse.net4j.util.event.IEvent; +import org.eclipse.net4j.util.event.IListener; import java.sql.Connection; import java.sql.SQLException; @@ -86,7 +91,7 @@ public final class DBDatabase extends SetContainer<IDBTransaction> implements ID return schemaTransaction; } - public void closeSchemaTransaction() + public void closeSchemaTransaction(DBSchemaDelta delta) { try { @@ -94,6 +99,8 @@ public final class DBDatabase extends SetContainer<IDBTransaction> implements ID { ((DBTransaction)transaction).invalidateStatementCache(); } + + fireEvent(new SchemaChangedEventImpl(delta)); } finally { @@ -107,31 +114,35 @@ public final class DBDatabase extends SetContainer<IDBTransaction> implements ID return schemaTransaction; } - public DBTransaction openTransaction() - { - DBTransaction transaction = new DBTransaction(this); - addElement(transaction); - return transaction; - } - - public void closeTransaction(DBTransaction transaction) - { - removeElement(transaction); - } - - public IDBTransaction[] getTransactions() - { - return getElements(); - } - - public int getStatementCacheCapacity() + public void ensureSchemaElement(RunnableWithSchema updateRunnable, final RunnableWithSchema commitRunnable) { - return statementCacheCapacity; - } + if (schemaTransaction != null) + { + DBSchema workingCopy = schemaTransaction.getWorkingCopy(); + updateRunnable.run(workingCopy); - public void setStatementCacheCapacity(int statementCacheCapacity) - { - this.statementCacheCapacity = statementCacheCapacity; + if (commitRunnable != null) + { + addListener(new IListener() + { + public void notifyEvent(IEvent event) + { + if (event instanceof SchemaChangedEvent) + { + commitRunnable.run(schema); + removeListener(this); + } + } + }); + } + } + else + { + if (commitRunnable != null) + { + commitRunnable.run(schema); + } + } } public <T extends IDBSchemaElement, P extends IDBSchemaElement> T ensureSchemaElement(P parent, Class<T> type, @@ -177,6 +188,33 @@ public final class DBDatabase extends SetContainer<IDBTransaction> implements ID }); } + public DBTransaction openTransaction() + { + DBTransaction transaction = new DBTransaction(this); + addElement(transaction); + return transaction; + } + + public void closeTransaction(DBTransaction transaction) + { + removeElement(transaction); + } + + public IDBTransaction[] getTransactions() + { + return getElements(); + } + + public int getStatementCacheCapacity() + { + return statementCacheCapacity; + } + + public void setStatementCacheCapacity(int statementCacheCapacity) + { + this.statementCacheCapacity = statementCacheCapacity; + } + public boolean isClosed() { return !isActive(); @@ -271,14 +309,14 @@ public final class DBDatabase extends SetContainer<IDBTransaction> implements ID /** * @author Eike Stepper */ - public interface SchemaAccess + private interface SchemaAccess { } /** * @author Eike Stepper */ - public final class ReadSchemaAccess implements SchemaAccess + private final class ReadSchemaAccess implements SchemaAccess { private int readers; @@ -302,7 +340,7 @@ public final class DBDatabase extends SetContainer<IDBTransaction> implements ID /** * @author Eike Stepper */ - public final class WriteSchemaAccess implements SchemaAccess + private final class WriteSchemaAccess implements SchemaAccess { @Override public String toString() @@ -310,4 +348,31 @@ public final class DBDatabase extends SetContainer<IDBTransaction> implements ID return "WRITER"; } } + + /** + * @author Eike Stepper + */ + private final class SchemaChangedEventImpl extends Event implements SchemaChangedEvent + { + private static final long serialVersionUID = 1L; + + private final IDBSchemaDelta schemaDelta; + + public SchemaChangedEventImpl(IDBSchemaDelta schemaDelta) + { + super(DBDatabase.this); + this.schemaDelta = schemaDelta; + } + + @Override + public IDBDatabase getSource() + { + return (IDBDatabase)super.getSource(); + } + + public IDBSchemaDelta getSchemaDelta() + { + return schemaDelta; + } + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java index c5da299906..823f8ede51 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java @@ -121,7 +121,7 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable finally { oldSchema.lock(); - close(); + doClose(delta); } return delta; @@ -129,9 +129,14 @@ public final class DBSchemaTransaction implements IDBSchemaTransaction, Runnable public void close() { + doClose(null); + } + + private void doClose(DBSchemaDelta delta) + { if (!isClosed()) { - database.closeSchemaTransaction(); + database.closeSchemaTransaction(delta); transaction = null; oldSchema = null; workingCopy = null; diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java index 1bd9cc0706..2ea7b4160a 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java @@ -137,12 +137,7 @@ public class DBIndex extends DBSchemaElement implements IDBIndex public IDBIndexField addIndexField(String name) throws SchemaElementNotFoundException { - DBField field = table.getField(name); - if (field == null) - { - throw new SchemaElementNotFoundException(this, SchemaElementType.FIELD, name); - } - + DBField field = table.getFieldSafe(name); return addIndexField(field); } @@ -168,6 +163,17 @@ public class DBIndex extends DBSchemaElement implements IDBIndex resetElements(); } + public DBIndexField getIndexFieldSafe(String name) throws SchemaElementNotFoundException + { + DBIndexField indexField = getIndexField(name); + if (indexField == null) + { + throw new SchemaElementNotFoundException(this, SchemaElementType.INDEX_FIELD, name); + } + + return indexField; + } + public DBIndexField getIndexField(String name) { return findElement(getIndexFields(), name); @@ -178,6 +184,12 @@ public class DBIndex extends DBSchemaElement implements IDBIndex return indexFields.get(position); } + public DBField getFieldSafe(String name) throws SchemaElementNotFoundException + { + DBIndexField indexField = getIndexFieldSafe(name); + return indexField.getField(); + } + public DBField getField(String name) { name = name(name); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java index fc3d939d0e..555bcd97bb 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java @@ -133,6 +133,17 @@ public class DBTable extends DBSchemaElement implements IDBTable resetElements(); } + public DBField getFieldSafe(String name) throws SchemaElementNotFoundException + { + DBField field = getField(name); + if (field == null) + { + throw new SchemaElementNotFoundException(this, SchemaElementType.FIELD, name); + } + + return field; + } + public DBField getField(String name) { return findElement(getFields(), name); @@ -158,11 +169,8 @@ public class DBTable extends DBSchemaElement implements IDBTable List<DBField> result = new ArrayList<DBField>(); for (String fieldName : fieldNames) { - DBField field = getField(fieldName); - if (field == null) - { - throw new SchemaElementNotFoundException(this, SchemaElementType.FIELD, fieldName); - } + DBField field = getFieldSafe(fieldName); + result.add(field); } return result.toArray(new DBField[result.size()]); @@ -217,7 +225,8 @@ public class DBTable extends DBSchemaElement implements IDBTable public DBIndex addIndex(IDBIndex.Type type, String... fieldNames) { - return addIndex(type, getFields(fieldNames)); + DBField[] fields = getFields(fieldNames); + return addIndex(type, fields); } public DBIndex addIndexEmpty(IDBIndex.Type type) @@ -248,6 +257,17 @@ public class DBTable extends DBSchemaElement implements IDBTable resetElements(); } + public DBIndex getIndexSafe(String name) throws SchemaElementNotFoundException + { + DBIndex index = getIndex(name); + if (index == null) + { + throw new SchemaElementNotFoundException(this, SchemaElementType.INDEX, name); + } + + return index; + } + public DBIndex getIndex(String name) { return findElement(getIndices(), name); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java index 5be3817622..8afdead23e 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java @@ -22,6 +22,7 @@ import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBSchemaElement; import org.eclipse.net4j.db.ddl.IDBSchemaVisitor; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.SchemaElementNotFoundException; import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; import org.eclipse.net4j.internal.db.ddl.DBField; import org.eclipse.net4j.internal.db.ddl.DBIndex; @@ -52,12 +53,12 @@ public class DBSchema extends DBSchemaElement implements IDBSchema private static final long serialVersionUID = 1L; + private static int indexCounter; + private Map<String, DBTable> tables = new HashMap<String, DBTable>(); private transient boolean locked; - private transient int indexCounter; - public DBSchema(String name) { super(name); @@ -216,6 +217,20 @@ public class DBSchema extends DBSchemaElement implements IDBSchema } /** + * @since 4.2 + */ + public final IDBTable getTableSafe(String name) throws SchemaElementNotFoundException + { + IDBTable table = getTable(name); + if (table == null) + { + throw new SchemaElementNotFoundException(this, SchemaElementType.TABLE, name); + } + + return table; + } + + /** * @since 2.0 */ public IDBTable getTable(String name) diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java index 988468aa64..c0c0320444 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ObjectUtil.java @@ -135,4 +135,17 @@ public final class ObjectUtil return null; } + + /** + * @since 3.3 + */ + public static <T> T notNull(T object) + { + if (object == null) + { + throw new NullPointerException(); + } + + return object; + } } |