/* * Copyright (c) 2012, 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.lissome.db; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.eresource.EresourcePackage; import org.eclipse.emf.cdo.server.internal.lissome.bundle.OM; import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.util.CDOURIUtil; import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.DBType; import org.eclipse.net4j.util.om.trace.ContextTracer; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * @author Eike Stepper */ public class IndexWriter extends IndexReader { private static final ContextTracer TRACER = new ContextTracer(OM.INDEX, IndexWriter.class); protected PreparedStatement addCommitInfoStatement; protected PreparedStatement addObjectStatement; protected PreparedStatement reviseOldRevisionsStatement; protected PreparedStatement createBranchStatement; private Set<PreparedStatement> batches = new HashSet<PreparedStatement>(); public IndexWriter(Index index) { super(index); try { connection.setAutoCommit(false); } catch (SQLException ex) { throw new DBException(ex); } } public void commit() { try { for (PreparedStatement stmt : batches) { stmt.executeBatch(); } connection.commit(); } catch (SQLException ex) { throw new DBException(ex); } finally { batches.clear(); } } protected void execute(PreparedStatement stmt) throws SQLException { index.trace(TRACER, stmt); stmt.addBatch(); batches.add(stmt); } public void addCommitInfo(CDOBranchPoint branchPoint, long pointer) { if (TRACER.isEnabled()) { TRACER.format("addCommitInfo: {0}, {1}", branchPoint, pointer); //$NON-NLS-1$ } try { if (addCommitInfoStatement == null) { String sql = index.commitInfos.sqlAddCommitInfo(); addCommitInfoStatement = connection.prepareStatement(sql); } int column = 0; long timeStamp = branchPoint.getTimeStamp(); addCommitInfoStatement.setLong(++column, timeStamp); if (supportingBranches) { CDOBranch branch = branchPoint.getBranch(); int branchID = branch.getID(); addCommitInfoStatement.setInt(++column, branchID); } addCommitInfoStatement.setLong(++column, pointer); execute(addCommitInfoStatement); } catch (SQLException ex) { throw new DBException(ex); } } public void addObjects(InternalCDORevision[] newRevisions, long[] pointers) { if (TRACER.isEnabled()) { TRACER.format("addObjects: {0}, {1}", Arrays.asList(newRevisions), Arrays.asList(pointers)); //$NON-NLS-1$ } try { if (addObjectStatement == null) { String sql = index.objects.sqlAddRevision(); addObjectStatement = connection.prepareStatement(sql); } for (int i = 0; i < newRevisions.length; i++) { InternalCDORevision revision = newRevisions[i]; long pointer = pointers[i]; boolean detached = revision instanceof DetachedCDORevision; int column = 0; CDOID oid = revision.getID(); index.setCDOID(addObjectStatement, ++column, oid); if (supportingBranches) { int branchID = revision.getBranch().getID(); addObjectStatement.setInt(++column, branchID); } if (supportingAudits) { long time = revision.getTimeStamp(); addObjectStatement.setLong(++column, time); long revised = revision.getRevised(); addObjectStatement.setLong(++column, revised); int version = revision.getVersion(); if (detached) { version = -version; } addObjectStatement.setInt(++column, version); } int cid = getStore().getMetaID(revision.getEClass()); addObjectStatement.setInt(++column, cid); CDOID containerID = detached ? CDOID.NULL : (CDOID)revision.getContainerID(); index.setCDOID(addObjectStatement, ++column, containerID); if (!detached && revision.isResourceNode()) { String name = (String)revision.data().get(EresourcePackage.Literals.CDO_RESOURCE_NODE__NAME, 0); if (name == null) { name = CDOURIUtil.SEGMENT_SEPARATOR; } addObjectStatement.setString(++column, name); } else { addObjectStatement.setNull(++column, DBType.VARCHAR.getCode()); } addObjectStatement.setLong(++column, pointer); execute(addObjectStatement); } } catch (SQLException ex) { throw new DBException(ex); } } public void updateObjects(InternalCDORevision[] newRevisions, long[] pointers) { if (TRACER.isEnabled()) { TRACER.format("updateObjects: {0}, {1}", Arrays.asList(newRevisions), Arrays.asList(pointers)); //$NON-NLS-1$ } if (supportingAudits) { reviseOldRevisions(newRevisions); addObjects(newRevisions, pointers); } else { // XXX } } protected void reviseOldRevisions(InternalCDORevision[] newRevisions) { if (TRACER.isEnabled()) { TRACER.format("reviseOldRevisions: {0}", Arrays.asList(newRevisions)); //$NON-NLS-1$ } try { if (reviseOldRevisionsStatement == null) { String sql = index.objects.sqlReviseOldRevisions(); reviseOldRevisionsStatement = connection.prepareStatement(sql); } for (int i = 0; i < newRevisions.length; i++) { InternalCDORevision revision = newRevisions[i]; int column = 0; long revised = revision.getTimeStamp() - 1; reviseOldRevisionsStatement.setLong(++column, revised); CDOID oid = revision.getID(); index.setCDOID(reviseOldRevisionsStatement, ++column, oid); if (supportingBranches) { int branchID = revision.getBranch().getID(); reviseOldRevisionsStatement.setInt(++column, branchID); } int version = Math.abs(revision.getVersion()) - 1; reviseOldRevisionsStatement.setInt(++column, version); execute(reviseOldRevisionsStatement); } } catch (SQLException ex) { throw new DBException(ex); } } public void detachObjects(CDOBranchPoint branchPoint, CDOID[] ids, InternalCDORevision[] detachedRevisions, long[] detachedObjectPointers) { if (TRACER.isEnabled()) { TRACER.format("detachObjects: {0}, {1}", Arrays.asList(ids), branchPoint); //$NON-NLS-1$ } if (supportingAudits) { updateObjects(detachedRevisions, detachedObjectPointers); } else { // TODO: implement IndexWriter.detachObjects(ids, types, branchPoint, pointers) throw new UnsupportedOperationException(); // long[] pointers = new long[ids.length]; // for (int i = 0; i < ids.length; i++) // { // CDOID id = ids[i]; // pointers[i] = readPointerNonAudit(id); // // // XXX Delete revision // } } } protected long readPointerNonAudit(CDOID id) { // TODO: implement IndexWriter.readPointerNonAudit(id) throw new UnsupportedOperationException(); } public void createBranch(int branchID, String name, CDOBranchPoint base, long pointer) { if (TRACER.isEnabled()) { TRACER.format("createBranch: {0}, {1}, {2}", branchID, name, base); //$NON-NLS-1$ } try { if (createBranchStatement == null) { String sql = index.branches.sqlCreateBranch(); createBranchStatement = connection.prepareStatement(sql); } createBranchStatement.setInt(1, branchID); createBranchStatement.setString(2, name); createBranchStatement.setInt(3, base.getBranch().getID()); createBranchStatement.setLong(4, base.getTimeStamp()); execute(createBranchStatement); } catch (SQLException ex) { throw new DBException(ex); } } }