Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java')
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java400
1 files changed, 400 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
new file mode 100644
index 0000000000..43ff0b5188
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
@@ -0,0 +1,400 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.model.CDOType;
+import org.eclipse.emf.cdo.internal.server.LongIDStore;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreUtil;
+import org.eclipse.emf.cdo.server.db.IClassMapping;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.db.IDBConnectionProvider;
+import org.eclipse.net4j.db.ddl.IDBSchema;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.spi.db.DBSchema;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import javax.sql.DataSource;
+
+import java.sql.Connection;
+import java.text.MessageFormat;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public class DBStore extends LongIDStore implements IDBStore
+{
+ public static final String TYPE = "db";
+
+ private IMappingStrategy mappingStrategy;
+
+ private IDBSchema dbSchema;
+
+ private IDBAdapter dbAdapter;
+
+ private IDBConnectionProvider dbConnectionProvider;
+
+ private int nextPackageID;
+
+ private int nextClassID;
+
+ private int nextFeatureID;
+
+ public DBStore()
+ {
+ super(TYPE);
+ }
+
+ public IMappingStrategy getMappingStrategy()
+ {
+ return mappingStrategy;
+ }
+
+ public void setMappingStrategy(IMappingStrategy mappingStrategy)
+ {
+ this.mappingStrategy = mappingStrategy;
+ mappingStrategy.setStore(this);
+ }
+
+ public IDBAdapter getDBAdapter()
+ {
+ return dbAdapter;
+ }
+
+ public void setDbAdapter(IDBAdapter dbAdapter)
+ {
+ this.dbAdapter = dbAdapter;
+ }
+
+ public IDBConnectionProvider getDBConnectionProvider()
+ {
+ return dbConnectionProvider;
+ }
+
+ public void setDbConnectionProvider(IDBConnectionProvider dbConnectionProvider)
+ {
+ this.dbConnectionProvider = dbConnectionProvider;
+ }
+
+ public void setDataSource(DataSource dataSource)
+ {
+ dbConnectionProvider = DBUtil.createConnectionProvider(dataSource);
+ }
+
+ public synchronized IDBSchema getDBSchema()
+ {
+ // TODO Better synchronization or eager init
+ if (dbSchema == null)
+ {
+ dbSchema = createSchema();
+ }
+
+ return dbSchema;
+ }
+
+ @Override
+ public boolean hasAuditingSupport()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean hasBranchingSupport()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean hasWriteDeltaSupport()
+ {
+ return false;
+ }
+
+ @Override
+ public DBStoreReader getReader(ISession session)
+ {
+ return (DBStoreReader)super.getReader(session);
+ }
+
+ @Override
+ public DBStoreReader createReader(ISession session) throws DBException
+ {
+ return new DBStoreReader(this, session);
+ }
+
+ @Override
+ public DBStoreWriter getWriter(IView view)
+ {
+ return (DBStoreWriter)super.getWriter(view);
+ }
+
+ @Override
+ public DBStoreWriter createWriter(IView view) throws DBException
+ {
+ return new DBStoreWriter(this, view);
+ }
+
+ public synchronized int getNextPackageID()
+ {
+ // TODO Better synchronization
+ return nextPackageID++;
+ }
+
+ public synchronized int getNextClassID()
+ {
+ // TODO Better synchronization
+ return nextClassID++;
+ }
+
+ public synchronized int getNextFeatureID()
+ {
+ // TODO Better synchronization
+ return nextFeatureID++;
+ }
+
+ public Connection getConnection()
+ {
+ Connection connection = dbConnectionProvider.getConnection();
+ if (connection == null)
+ {
+ throw new DBException("No connection from connection provider: " + dbConnectionProvider);
+ }
+
+ return connection;
+ }
+
+ @Override
+ protected void doBeforeActivate() throws Exception
+ {
+ super.doBeforeActivate();
+ checkNull(mappingStrategy, "mappingStrategy is null");
+ checkNull(dbAdapter, "dbAdapter is null");
+ checkNull(dbConnectionProvider, "dbConnectionProvider is null");
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+ Connection connection = null;
+
+ try
+ {
+ connection = getConnection();
+ Set<IDBTable> createdTables = CDODBSchema.INSTANCE.create(dbAdapter, dbConnectionProvider);
+ if (createdTables.contains(CDODBSchema.REPOSITORY))
+ {
+ // First start
+ DBUtil.insertRow(connection, dbAdapter, CDODBSchema.REPOSITORY, 1, getStartupTime(), 0, CRASHED, CRASHED);
+
+ MappingStrategy mappingStrategy = (MappingStrategy)getMappingStrategy();
+
+ IClassMapping resourceClassMapping = mappingStrategy.getResourceClassMapping();
+ Set<IDBTable> tables = resourceClassMapping.getAffectedTables();
+ if (dbAdapter.createTables(tables, connection).size() != tables.size())
+ {
+ throw new DBException("CDOResource tables not completely created");
+ }
+ }
+ else
+ {
+ // Restart
+ long lastObjectID = DBUtil.selectMaximumLong(connection, CDODBSchema.REPOSITORY_NEXT_CDOID);
+ setLastMetaID(DBUtil.selectMaximumLong(connection, CDODBSchema.REPOSITORY_NEXT_METAID));
+ if (lastObjectID == CRASHED || getLastMetaID() == CRASHED)
+ {
+ OM.LOG.warn("Detected restart after crash");
+ }
+
+ setLastObjectID(lastObjectID);
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("UPDATE ");
+ builder.append(CDODBSchema.REPOSITORY);
+ builder.append(" SET ");
+ builder.append(CDODBSchema.REPOSITORY_STARTS);
+ builder.append("=");
+ builder.append(CDODBSchema.REPOSITORY_STARTS);
+ builder.append("+1, ");
+ builder.append(CDODBSchema.REPOSITORY_STARTED);
+ builder.append("=");
+ builder.append(getStartupTime());
+ builder.append(", ");
+ builder.append(CDODBSchema.REPOSITORY_STOPPED);
+ builder.append("=0, ");
+ builder.append(CDODBSchema.REPOSITORY_NEXT_CDOID);
+ builder.append("=");
+ builder.append(CRASHED);
+ builder.append(", ");
+ builder.append(CDODBSchema.REPOSITORY_NEXT_METAID);
+ builder.append("=");
+ builder.append(CRASHED);
+
+ String sql = builder.toString();
+ int count = DBUtil.update(connection, sql);
+ if (count == 0)
+ {
+ throw new DBException("No row updated in table " + CDODBSchema.REPOSITORY);
+ }
+ }
+
+ nextPackageID = DBUtil.selectMaximumInt(connection, CDODBSchema.PACKAGES_ID) + 1;
+ nextClassID = DBUtil.selectMaximumInt(connection, CDODBSchema.CLASSES_ID) + 1;
+ nextFeatureID = DBUtil.selectMaximumInt(connection, CDODBSchema.FEATURES_ID) + 1;
+ LifecycleUtil.activate(mappingStrategy);
+ }
+ finally
+ {
+ DBUtil.close(connection);
+ }
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ Connection connection = null;
+
+ try
+ {
+ connection = getConnection();
+
+ LifecycleUtil.deactivate(mappingStrategy);
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("UPDATE ");
+ builder.append(CDODBSchema.REPOSITORY);
+ builder.append(" SET ");
+ builder.append(CDODBSchema.REPOSITORY_STOPPED);
+ builder.append("=");
+ builder.append(getShutdownTime());
+ builder.append(", ");
+ builder.append(CDODBSchema.REPOSITORY_NEXT_CDOID);
+ builder.append("=");
+ builder.append(getLastObjectID());
+ builder.append(", ");
+ builder.append(CDODBSchema.REPOSITORY_NEXT_METAID);
+ builder.append("=");
+ builder.append(getRepository().getLastMetaID());
+
+ String sql = builder.toString();
+ int count = DBUtil.update(connection, sql);
+ if (count == 0)
+ {
+ throw new DBException("No row updated in table " + CDODBSchema.REPOSITORY);
+ }
+ }
+ finally
+ {
+ DBUtil.close(connection);
+ }
+
+ super.doDeactivate();
+ }
+
+ @Override
+ public void repairAfterCrash()
+ {
+ DBStoreReader storeReader = getReader(null);
+ StoreUtil.setReader(storeReader);
+
+ try
+ {
+ Connection connection = storeReader.getConnection();
+ long maxObjectID = mappingStrategy.repairAfterCrash(connection);
+ setLastMetaID(DBUtil.selectMaximumLong(connection, CDODBSchema.PACKAGES_RANGE_UB));
+
+ OM.LOG.info(MessageFormat.format("Repaired after crash: maxObjectID={0}, maxMetaID={1}", maxObjectID,
+ getLastMetaID()));
+ setLastObjectID(maxObjectID);
+ }
+ finally
+ {
+ storeReader.release();
+ StoreUtil.setReader(null);
+ }
+ }
+
+ protected IDBSchema createSchema()
+ {
+ String name = getRepository().getName();
+ return new DBSchema(name);
+ }
+
+ protected long getStartupTime()
+ {
+ return System.currentTimeMillis();
+ }
+
+ protected long getShutdownTime()
+ {
+ return System.currentTimeMillis();
+ }
+
+ public static DBType getDBType(CDOType type)
+ {
+ if (type == CDOType.BOOLEAN || type == CDOType.BOOLEAN_OBJECT)
+ {
+ return DBType.BOOLEAN;
+ }
+ else if (type == CDOType.BYTE || type == CDOType.BYTE_OBJECT)
+ {
+ return DBType.SMALLINT;
+ }
+ else if (type == CDOType.CHAR || type == CDOType.CHARACTER_OBJECT)
+ {
+ return DBType.CHAR;
+ }
+ else if (type == CDOType.DATE)
+ {
+ return DBType.DATE;
+ }
+ else if (type == CDOType.DOUBLE || type == CDOType.DOUBLE_OBJECT)
+ {
+ return DBType.DOUBLE;
+ }
+ else if (type == CDOType.FLOAT || type == CDOType.FLOAT_OBJECT)
+ {
+ return DBType.FLOAT;
+ }
+ else if (type == CDOType.INT || type == CDOType.INTEGER_OBJECT)
+ {
+ return DBType.INTEGER;
+ }
+ else if (type == CDOType.LONG || type == CDOType.LONG_OBJECT)
+ {
+ return DBType.BIGINT;
+ }
+ else if (type == CDOType.OBJECT)
+ {
+ return DBType.BIGINT;
+ }
+ else if (type == CDOType.SHORT || type == CDOType.SHORT_OBJECT)
+ {
+ return DBType.SMALLINT;
+ }
+ else if (type == CDOType.STRING || type == CDOType.CUSTOM)
+ {
+ return DBType.VARCHAR;
+ }
+
+ throw new ImplementationError("Unrecognized CDOType: " + type);
+ }
+}

Back to the top