Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CommitInfoTable.java')
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CommitInfoTable.java370
1 files changed, 370 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CommitInfoTable.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CommitInfoTable.java
new file mode 100644
index 0000000000..b42431b0a3
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CommitInfoTable.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2016 Eike Stepper (Berlin, Germany) and others.
+ * 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.CDOCommonRepository.CommitInfoStorage;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBDatabase;
+import org.eclipse.net4j.db.IDBDatabase.RunnableWithSchema;
+import org.eclipse.net4j.db.IDBPreparedStatement;
+import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex;
+import org.eclipse.net4j.db.ddl.IDBSchema;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author Eike Stepper
+ * @since 4.6
+ */
+public class CommitInfoTable extends Lifecycle
+{
+ private static final String COMMIT_INFOS = "cdo_commit_infos"; //$NON-NLS-1$
+
+ private static final String TIMESTAMP = "commit_time"; //$NON-NLS-1$
+
+ private static final String PREVIOUS_TIMESTAMP = "previous_time";
+
+ private static final String BRANCH = "branch_id"; //$NON-NLS-1$
+
+ private static final String USER = "user_id"; //$NON-NLS-1$
+
+ private static final String COMMENT = "commit_comment"; //$NON-NLS-1$
+
+ private static final String MERGED_BRANCH = "merged_branch"; //$NON-NLS-1$
+
+ private static final String MERGED_TIMESTAMP = "merged_time"; //$NON-NLS-1$
+
+ private DBStore store;
+
+ private boolean withMergeSource;
+
+ private IDBTable table;
+
+ private String sqlInsert;
+
+ public CommitInfoTable(DBStore store)
+ {
+ this.store = store;
+ }
+
+ public void writeCommitInfo(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, long previousTimeStamp,
+ String userID, String comment, CDOBranchPoint mergeSource, OMMonitor monitor)
+ {
+ IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sqlInsert, ReuseProbability.HIGH);
+
+ try
+ {
+ stmt.setLong(1, timeStamp);
+ stmt.setLong(2, previousTimeStamp);
+ stmt.setInt(3, branch.getID());
+ stmt.setString(4, userID);
+ stmt.setString(5, comment);
+
+ if (withMergeSource)
+ {
+ if (mergeSource != null)
+ {
+ stmt.setInt(6, mergeSource.getBranch().getID());
+ stmt.setLong(7, mergeSource.getTimeStamp());
+ }
+ else
+ {
+ stmt.setNull(6, DBType.INTEGER.getCode());
+ stmt.setNull(7, DBType.BIGINT.getCode());
+ }
+ }
+
+ DBUtil.update(stmt, true);
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ DBUtil.close(stmt);
+ }
+ }
+
+ public void loadCommitInfos(IDBStoreAccessor accessor, CDOBranch branch, long startTime, long endTime,
+ CDOCommitInfoHandler handler)
+ {
+ int count = CDOCommitInfoUtil.decodeCount(endTime);
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("SELECT "); //$NON-NLS-1$
+ builder.append(TIMESTAMP);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(PREVIOUS_TIMESTAMP);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(USER);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(COMMENT);
+
+ if (branch == null)
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(BRANCH);
+ }
+
+ if (withMergeSource)
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(MERGED_BRANCH);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(MERGED_TIMESTAMP);
+ }
+
+ builder.append(" FROM "); //$NON-NLS-1$
+ builder.append(COMMIT_INFOS);
+ boolean where = false;
+
+ if (branch != null)
+ {
+ builder.append(where ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+ builder.append(BRANCH);
+ builder.append("="); //$NON-NLS-1$
+ builder.append(branch.getID());
+ where = true;
+ }
+
+ if (startTime != CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ builder.append(where ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+ builder.append(TIMESTAMP);
+ builder.append(count < 0 ? "<=" : ">="); //$NON-NLS-1$
+ builder.append(startTime);
+ where = true;
+ }
+
+ if (endTime > CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ builder.append(where ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+ builder.append(TIMESTAMP);
+ builder.append("<="); //$NON-NLS-1$
+ builder.append(endTime);
+ where = true;
+ }
+
+ builder.append(" ORDER BY "); //$NON-NLS-1$
+ builder.append(TIMESTAMP);
+ builder.append(count < 0 || CDOBranchPoint.UNSPECIFIED_DATE <= endTime && endTime <= startTime ? " DESC" : " ASC"); //$NON-NLS-1$
+ String sql = builder.toString();
+
+ IDBPreparedStatement stmt = accessor.getDBConnection().prepareStatement(sql, ReuseProbability.LOW);
+ ResultSet resultSet = null;
+
+ InternalRepository repository = store.getRepository();
+ InternalCDOBranchManager branchManager = repository.getBranchManager();
+ InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
+ count = Math.abs(count);
+
+ try
+ {
+ resultSet = stmt.executeQuery();
+ while (count-- > 0 && resultSet.next())
+ {
+ int column = 0;
+
+ long timeStamp = resultSet.getLong(++column);
+ long previousTimeStamp = resultSet.getLong(++column);
+ String userID = resultSet.getString(++column);
+ String comment = resultSet.getString(++column);
+
+ CDOBranch infoBranch = branch;
+ if (infoBranch == null)
+ {
+ int id = resultSet.getInt(++column);
+ infoBranch = branchManager.getBranch(id);
+ }
+
+ CDOBranchPoint mergeSource = null;
+ if (withMergeSource)
+ {
+ int id = resultSet.getInt(++column);
+ if (!resultSet.wasNull())
+ {
+ InternalCDOBranch mergedBranch = branchManager.getBranch(id);
+
+ long mergedTimeStamp = resultSet.getLong(++column);
+ mergeSource = mergedBranch.getPoint(mergedTimeStamp);
+ }
+ }
+
+ CDOCommitInfo commitInfo = commitInfoManager.createCommitInfo(infoBranch, timeStamp, previousTimeStamp, userID,
+ comment, mergeSource, null);
+ handler.handleCommitInfo(commitInfo);
+ }
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
+ finally
+ {
+ DBUtil.close(resultSet);
+ DBUtil.close(stmt);
+ }
+ }
+
+ public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
+ throws IOException
+ {
+ out.writeBoolean(withMergeSource);
+
+ String where = " WHERE " + TIMESTAMP + " BETWEEN " + fromCommitTime + " AND " + toCommitTime;
+ DBUtil.serializeTable(out, connection, table, null, where);
+ }
+
+ public void rawImport(Connection connection, CDODataInput in, long fromCommitTime, long toCommitTime,
+ OMMonitor monitor) throws IOException
+ {
+ boolean actualWithMergeSource = in.readBoolean();
+ if (actualWithMergeSource != withMergeSource)
+ {
+ throw new IllegalStateException("Commit info data mismatch. Expected: " + (withMergeSource ? "with" : "without")
+ + " merge source. Actual: " + (actualWithMergeSource ? "with" : "without") + " merge source.");
+ }
+
+ DBUtil.deserializeTable(in, connection, table, monitor.fork());
+ }
+
+ public void repairAfterCrash(Connection connection)
+ {
+ IDBField timeStampField = table.getField(TIMESTAMP);
+
+ long lastCommitTime = DBUtil.selectMaximumLong(connection, timeStampField);
+ long lastNonLocalCommitTime = DBUtil.selectMaximumLong(connection, timeStampField,
+ CDOBranch.MAIN_BRANCH_ID + "<=" + BRANCH);
+
+ if (lastNonLocalCommitTime == CDOBranchPoint.UNSPECIFIED_DATE)
+ {
+ lastNonLocalCommitTime = lastCommitTime;
+ }
+
+ store.setLastCommitTime(lastCommitTime);
+ store.setLastNonLocalCommitTime(lastNonLocalCommitTime);
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+
+ InternalRepository repository = store.getRepository();
+ withMergeSource = repository.getCommitInfoStorage() == CommitInfoStorage.WITH_MERGE_SOURCE;
+
+ IDBDatabase database = store.getDatabase();
+ table = database.getSchema().getTable(COMMIT_INFOS);
+ if (table == null)
+ {
+ database.updateSchema(new RunnableWithSchema()
+ {
+ public void run(IDBSchema schema)
+ {
+ table = schema.addTable(COMMIT_INFOS);
+ table.addField(TIMESTAMP, DBType.BIGINT, true);
+ table.addField(PREVIOUS_TIMESTAMP, DBType.BIGINT);
+ table.addField(BRANCH, DBType.INTEGER);
+ table.addField(USER, DBType.VARCHAR);
+ table.addField(COMMENT, DBType.VARCHAR);
+ table.addIndex(IDBIndex.Type.PRIMARY_KEY, TIMESTAMP);
+ table.addIndex(IDBIndex.Type.NON_UNIQUE, BRANCH);
+
+ if (withMergeSource)
+ {
+ table.addField(MERGED_BRANCH, DBType.INTEGER);
+ table.addField(MERGED_TIMESTAMP, DBType.BIGINT);
+ table.addIndex(IDBIndex.Type.NON_UNIQUE, MERGED_BRANCH, MERGED_TIMESTAMP);
+ }
+ }
+ });
+ }
+ else
+ {
+ if (withMergeSource && table.getField(MERGED_BRANCH) == null)
+ {
+ database.updateSchema(new RunnableWithSchema()
+ {
+ public void run(IDBSchema schema)
+ {
+ IDBTable table = schema.getTable(COMMIT_INFOS);
+ table.addField(MERGED_BRANCH, DBType.INTEGER);
+ table.addField(MERGED_TIMESTAMP, DBType.BIGINT);
+ table.addIndex(IDBIndex.Type.NON_UNIQUE, MERGED_BRANCH, MERGED_TIMESTAMP);
+ }
+ });
+ }
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("INSERT INTO "); //$NON-NLS-1$
+ builder.append(COMMIT_INFOS);
+ builder.append("("); //$NON-NLS-1$
+ builder.append(TIMESTAMP);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(PREVIOUS_TIMESTAMP);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(BRANCH);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(USER);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(COMMENT);
+
+ if (withMergeSource)
+ {
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(MERGED_BRANCH);
+ builder.append(", "); //$NON-NLS-1$
+ builder.append(MERGED_TIMESTAMP);
+ }
+
+ builder.append(") VALUES (?, ?, ?, ?, ?"); //$NON-NLS-1$
+ if (withMergeSource)
+ {
+ builder.append(", ?, ?"); //$NON-NLS-1$
+ }
+
+ builder.append(")"); //$NON-NLS-1$
+ sqlInsert = builder.toString();
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ sqlInsert = null;
+ table = null;
+ super.doDeactivate();
+ }
+}

Back to the top