diff options
author | Eike Stepper | 2010-02-02 11:39:48 +0000 |
---|---|---|
committer | Eike Stepper | 2010-02-02 11:39:48 +0000 |
commit | dc758eb87d5c2f0e802e49de4ca6173d3d94a2c8 (patch) | |
tree | ee1091aac506313694923c73871275551cbc714d /plugins/org.eclipse.emf.cdo.common | |
parent | 09f6a7f80829204abd2c2bf2511ba3b4e65c81c8 (diff) | |
download | cdo-dc758eb87d5c2f0e802e49de4ca6173d3d94a2c8.tar.gz cdo-dc758eb87d5c2f0e802e49de4ca6173d3d94a2c8.tar.xz cdo-dc758eb87d5c2f0e802e49de4ca6173d3d94a2c8.zip |
[270716] Provide support for branching
https://bugs.eclipse.org/bugs/show_bug.cgi?id=270716
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.common')
64 files changed, 5277 insertions, 1230 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF index f1332ab0fa..eec3a4b403 100644 --- a/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.common/META-INF/MANIFEST.MF @@ -34,7 +34,17 @@ Export-Package: org.eclipse.emf.cdo.common;version="3.0.0", org.eclipse.emf.cdo.server.net4j, org.eclipse.emf.cdo.ui, org.eclipse.emf.cdo.tests", + org.eclipse.emf.cdo.internal.common.branch;version="3.0.0";x-friends:="org.eclipse.emf.cdo.tests", org.eclipse.emf.cdo.internal.common.bundle;version="3.0.0";x-internal:=true, + org.eclipse.emf.cdo.internal.common.commit;version="3.0.0"; + x-friends:="org.eclipse.emf.cdo.common, + org.eclipse.emf.cdo.common.db, + org.eclipse.emf.cdo, + org.eclipse.emf.cdo.net4j, + org.eclipse.emf.cdo.server, + org.eclipse.emf.cdo.server.net4j, + org.eclipse.emf.cdo.ui, + org.eclipse.emf.cdo.tests", org.eclipse.emf.cdo.internal.common.id;version="3.0.0"; x-friends:="org.eclipse.emf.cdo.common, org.eclipse.emf.cdo.common.db, @@ -81,6 +91,15 @@ Export-Package: org.eclipse.emf.cdo.common;version="3.0.0", org.eclipse.emf.cdo.server.net4j, org.eclipse.emf.cdo.ui, org.eclipse.emf.cdo.tests", + org.eclipse.emf.cdo.internal.common.revision.cache.branch;version="3.0.0"; + x-friends:="org.eclipse.emf.cdo.common, + org.eclipse.emf.cdo.common.db, + org.eclipse.emf.cdo, + org.eclipse.emf.cdo.net4j, + org.eclipse.emf.cdo.server, + org.eclipse.emf.cdo.server.net4j, + org.eclipse.emf.cdo.ui, + org.eclipse.emf.cdo.tests", org.eclipse.emf.cdo.internal.common.revision.cache.lru;version="3.0.0"; x-friends:="org.eclipse.emf.cdo.common, org.eclipse.emf.cdo.common.db, @@ -127,6 +146,7 @@ Export-Package: org.eclipse.emf.cdo.common;version="3.0.0", org.eclipse.emf.cdo.ui, org.eclipse.emf.cdo.tests", org.eclipse.emf.cdo.spi.common;version="3.0.0", + org.eclipse.emf.cdo.spi.common.branch;version="3.0.0", org.eclipse.emf.cdo.spi.common.id;version="3.0.0", org.eclipse.emf.cdo.spi.common.model;version="3.0.0", org.eclipse.emf.cdo.spi.common.revision;version="3.0.0" diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOCommonView.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOCommonView.java index 02a9028f2f..2e1c8e7cb6 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOCommonView.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOCommonView.java @@ -4,13 +4,13 @@ * 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.common; -import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.net4j.util.collection.Closeable; @@ -18,23 +18,14 @@ import org.eclipse.net4j.util.collection.Closeable; * @author Eike Stepper * @since 2.0 */ -public interface CDOCommonView extends Closeable +public interface CDOCommonView extends CDOBranchPoint, Closeable { - public static final long UNSPECIFIED_DATE = CDORevision.UNSPECIFIED_DATE; - public int getViewID(); - public Type getViewType(); - - public CDOCommonSession getSession(); - - public long getTimeStamp(); - /** - * @author Eike Stepper + * @since 3.0 */ - public enum Type - { - TRANSACTION, READONLY, AUDIT - } + public boolean isReadOnly(); + + public CDOCommonSession getSession(); } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOTimeProvider.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOTimeProvider.java new file mode 100644 index 0000000000..206b31c165 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOTimeProvider.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2004 - 2009 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.common; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface CDOTimeProvider +{ + public long getTimeStamp(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java index eb1eb8808c..cbb5aeae7e 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranch.java @@ -14,11 +14,35 @@ package org.eclipse.emf.cdo.common.branch; * @author Eike Stepper * @since 3.0 */ -public interface CDOBranch +public interface CDOBranch extends Comparable<CDOBranch> { + public static final int MAIN_BRANCH_ID = 0; + + public static final String MAIN_BRANCH_NAME = "MAIN"; + + public static final String PATH_SEPARATOR = "/"; + + public boolean isMainBranch(); + public int getID(); public String getName(); - public CDOBranchTag getBase(); + public CDOBranchPoint getBase(); + + public CDOBranchPoint getHead(); + + public CDOBranchPoint getPoint(long timeStamp); + + public CDOBranchVersion getVersion(int version); + + public CDOBranchManager getBranchManager(); + + public CDOBranch[] getBranches(); + + public CDOBranch getBranch(String path); + + public CDOBranch createBranch(String name, long timeStamp); + + public CDOBranch createBranch(String name); } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchCreatedEvent.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchCreatedEvent.java new file mode 100644 index 0000000000..a3ce7d4414 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchCreatedEvent.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2004 - 2009 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.common.branch; + +import org.eclipse.net4j.util.event.IEvent; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface CDOBranchCreatedEvent extends IEvent +{ + public CDOBranchManager getSource(); + + public CDOBranch getBranch(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java new file mode 100644 index 0000000000..c4068048af --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchManager.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2004 - 2009 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.common.branch; + +import org.eclipse.net4j.util.event.INotifier; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface CDOBranchManager extends INotifier +{ + public CDOBranch getMainBranch(); + + public CDOBranch getBranch(int branchID); + + public CDOBranch getBranch(String path); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchPoint.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchPoint.java index 0e70230699..91751bf5c1 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchPoint.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchPoint.java @@ -10,14 +10,15 @@ */ package org.eclipse.emf.cdo.common.branch; - /** * @author Eike Stepper * @since 3.0 */ -public interface CDOBranchPoint +public interface CDOBranchPoint extends Comparable<CDOBranchPoint> { - public int getBranchID(); + public static final long UNSPECIFIED_DATE = 0; + + public CDOBranch getBranch(); public long getTimeStamp(); } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java index fe9ec5d7ea..6311666ca3 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchTag.java @@ -10,7 +10,6 @@ */ package org.eclipse.emf.cdo.common.branch; - /** * @author Eike Stepper * @since 3.0 diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchVersion.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchVersion.java new file mode 100644 index 0000000000..93188e7935 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/branch/CDOBranchVersion.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2004 - 2009 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.common.branch; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface CDOBranchVersion +{ + public static final int UNSPECIFIED_VERSION = 0; + + public static final int FIRST_VERSION = 1; + + public CDOBranch getBranch(); + + public int getVersion(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/commit/CDOCommit.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/commit/CDOCommit.java index 26c7695ff7..772da37ae6 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/commit/CDOCommit.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/commit/CDOCommit.java @@ -12,8 +12,6 @@ package org.eclipse.emf.cdo.common.commit; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; -import java.util.List; - /** * @author Eike Stepper * @since 3.0 @@ -22,7 +20,7 @@ public interface CDOCommit extends CDOBranchPoint { public String getUserID(); - public List<String> getComments(); + public String getComment(); // public Set<CDOID> getNewResources(); // diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndBranch.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndBranch.java new file mode 100644 index 0000000000..a304991f75 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndBranch.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2004 - 2009 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.common.id; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; + +/** + * @author Eike Stepper + * @noimplement This interface is not intended to be implemented by clients. + * @since 3.0 + */ +public interface CDOIDAndBranch +{ + public CDOID getID(); + + public CDOBranch getBranch(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndVersion.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndVersion.java index 90ae24eba3..3297607236 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndVersion.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndVersion.java @@ -4,7 +4,7 @@ * 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 */ diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndVersionAndBranch.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndVersionAndBranch.java new file mode 100644 index 0000000000..3959c96211 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDAndVersionAndBranch.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2004 - 2009 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.common.id; + + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface CDOIDAndVersionAndBranch extends CDOIDAndVersion +{ + public int getBranchID(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDUtil.java index 0548603299..82ac77409e 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/id/CDOIDUtil.java @@ -13,9 +13,12 @@ */ package org.eclipse.emf.cdo.common.id; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.id.CDOID.Type; import org.eclipse.emf.cdo.common.model.CDOClassifierRef; import org.eclipse.emf.cdo.internal.common.bundle.OM; +import org.eclipse.emf.cdo.internal.common.id.CDOIDAndBranchImpl; +import org.eclipse.emf.cdo.internal.common.id.CDOIDAndVersionAndBranchImpl; import org.eclipse.emf.cdo.internal.common.id.CDOIDAndVersionImpl; import org.eclipse.emf.cdo.internal.common.id.CDOIDExternalImpl; import org.eclipse.emf.cdo.internal.common.id.CDOIDMetaImpl; @@ -351,6 +354,22 @@ public final class CDOIDUtil } /** + * @since 3.0 + */ + public static CDOIDAndBranch createIDAndBranch(CDOID id, CDOBranch branch) + { + return new CDOIDAndBranchImpl(id, branch); + } + + /** + * @since 3.0 + */ + public static CDOIDAndVersionAndBranch createIDAndVersionAndBranch(CDOID id, int version, int branchID) + { + return new CDOIDAndVersionAndBranchImpl(id, version, branchID); + } + + /** * @since 2.0 */ public static boolean equals(CDOID id1, CDOID id2) diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataInput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataInput.java index 9d44dfc0e7..d746ab8195 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataInput.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataInput.java @@ -11,8 +11,13 @@ */ package org.eclipse.emf.cdo.common.io; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDAndVersion; +import org.eclipse.emf.cdo.common.id.CDOIDAndVersionAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDMetaRange; import org.eclipse.emf.cdo.common.model.CDOClassifierRef; import org.eclipse.emf.cdo.common.model.CDOPackageInfo; @@ -59,10 +64,37 @@ public interface CDODataInput extends ExtendedDataInput // ///////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @since 3.0 + */ + public CDOBranch readCDOBranch() throws IOException; + + /** + * @since 3.0 + */ + public CDOBranchPoint readCDOBranchPoint() throws IOException; + + /** + * @since 3.0 + */ + public CDOBranchVersion readCDOBranchVersion() throws IOException; + + // ///////////////////////////////////////////////////////////////////////////////////////////////// + public CDOID readCDOID() throws IOException; public CDOIDAndVersion readCDOIDAndVersion() throws IOException; + /** + * @since 3.0 + */ + public CDOIDAndBranch readCDOIDAndBranch() throws IOException; + + /** + * @since 3.0 + */ + public CDOIDAndVersionAndBranch readCDOIDAndVersionAndBranch() throws IOException; + public CDOIDMetaRange readCDOIDMetaRange() throws IOException; // ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataOutput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataOutput.java index aa391edec4..fa7fca9c35 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataOutput.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/io/CDODataOutput.java @@ -11,8 +11,13 @@ */ package org.eclipse.emf.cdo.common.io; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDAndVersion; +import org.eclipse.emf.cdo.common.id.CDOIDAndVersionAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDMetaRange; import org.eclipse.emf.cdo.common.id.CDOIDProvider; import org.eclipse.emf.cdo.common.model.CDOClassifierRef; @@ -67,10 +72,37 @@ public interface CDODataOutput extends ExtendedDataOutput // ///////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @since 3.0 + */ + public void writeCDOBranch(CDOBranch branch) throws IOException; + + /** + * @since 3.0 + */ + public void writeCDOBranchPoint(CDOBranchPoint branchPoint) throws IOException; + + /** + * @since 3.0 + */ + public void writeCDOBranchVersion(CDOBranchVersion branchVersion) throws IOException; + + // ///////////////////////////////////////////////////////////////////////////////////////////////// + public void writeCDOID(CDOID id) throws IOException; public void writeCDOIDAndVersion(CDOIDAndVersion idAndVersion) throws IOException; + /** + * @since 3.0 + */ + public void writeCDOIDAndBranch(CDOIDAndBranch idAndBranch) throws IOException; + + /** + * @since 3.0 + */ + public void writeCDOIDAndVersionAndBranch(CDOIDAndVersionAndBranch idAndVersionAndBranch) throws IOException; + public void writeCDOIDMetaRange(CDOIDMetaRange metaRange) throws IOException; // ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java index 1935038576..b2eb4dc15f 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java @@ -29,67 +29,97 @@ public interface CDOProtocolConstants public static final short SIGNAL_AUTHENTICATION = 2; - public static final short SIGNAL_VIEWS_CHANGED = 4; + /** + * @since 3.0 + */ + public static final short SIGNAL_OPEN_VIEW = 3; + + /** + * @since 3.0 + */ + public static final short SIGNAL_CHANGE_VIEW = 4; + + /** + * @since 3.0 + */ + public static final short SIGNAL_CLOSE_VIEW = 5; public static final short SIGNAL_LOAD_PACKAGES = 6; - public static final short SIGNAL_LOAD_REVISION = 7; + /** + * @since 3.0 + */ + public static final short SIGNAL_LOAD_REVISIONS = 7; + + public static final short SIGNAL_LOAD_REVISION_BY_VERSION = 8; - public static final short SIGNAL_LOAD_REVISION_BY_TIME = 8; + public static final short SIGNAL_LOAD_CHUNK = 9; - public static final short SIGNAL_LOAD_REVISION_BY_VERSION = 9; + public static final short SIGNAL_COMMIT_TRANSACTION = 10; - public static final short SIGNAL_LOAD_CHUNK = 10; + public static final short SIGNAL_COMMIT_TRANSACTION_PHASE1 = 11; - public static final short SIGNAL_VERIFY_REVISION = 11; + public static final short SIGNAL_COMMIT_TRANSACTION_PHASE2 = 12; - public static final short SIGNAL_COMMIT_TRANSACTION = 12; + public static final short SIGNAL_COMMIT_TRANSACTION_PHASE3 = 13; - public static final short SIGNAL_COMMIT_TRANSACTION_PHASE1 = 13; + public static final short SIGNAL_COMMIT_TRANSACTION_CANCEL = 14; - public static final short SIGNAL_COMMIT_TRANSACTION_PHASE2 = 14; + public static final short SIGNAL_COMMIT_NOTIFICATION = 15; - public static final short SIGNAL_COMMIT_TRANSACTION_PHASE3 = 15; + public static final short SIGNAL_QUERY = 16; - public static final short SIGNAL_COMMIT_TRANSACTION_CANCEL = 16; + public static final short SIGNAL_QUERY_CANCEL = 17; - public static final short SIGNAL_COMMIT_NOTIFICATION = 17; + public static final short SIGNAL_SYNC_REVISIONS = 18; - public static final short SIGNAL_QUERY = 18; + public static final short SIGNAL_PASSIVE_UPDATE = 19; - public static final short SIGNAL_QUERY_CANCEL = 19; + public static final short SIGNAL_CHANGE_SUBSCRIPTION = 20; - public static final short SIGNAL_SYNC_REVISIONS = 20; + public static final short SIGNAL_REPOSITORY_TIME = 21; - public static final short SIGNAL_PASSIVE_UPDATE = 21; + public static final short SIGNAL_LOCK_OBJECTS = 22; - public static final short SIGNAL_CHANGE_SUBSCRIPTION = 22; + public static final short SIGNAL_UNLOCK_OBJECTS = 23; - public static final short SIGNAL_SET_AUDIT = 23; + public static final short SIGNAL_OBJECT_LOCKED = 24; - public static final short SIGNAL_REPOSITORY_TIME = 24; + public static final short SIGNAL_GET_REMOTE_SESSIONS = 25; - public static final short SIGNAL_LOCK_OBJECTS = 25; + /** + * @since 3.0 + */ + public static final short SIGNAL_REMOTE_MESSAGE = 26; - public static final short SIGNAL_UNLOCK_OBJECTS = 26; + /** + * @since 3.0 + */ + public static final short SIGNAL_REMOTE_MESSAGE_NOTIFICATION = 27; - public static final short SIGNAL_OBJECT_LOCKED = 27; + public static final short SIGNAL_UNSUBSCRIBE_REMOTE_SESSIONS = 28; - public static final short SIGNAL_GET_REMOTE_SESSIONS = 28; + public static final short SIGNAL_REMOTE_SESSION_NOTIFICATION = 29; /** * @since 3.0 */ - public static final short SIGNAL_REMOTE_MESSAGE = 29; + public static final short SIGNAL_CREATE_BRANCH = 30; /** * @since 3.0 */ - public static final short SIGNAL_REMOTE_MESSAGE_NOTIFICATION = 30; + public static final short SIGNAL_LOAD_BRANCH = 31; - public static final short SIGNAL_UNSUBSCRIBE_REMOTE_SESSIONS = 31; + /** + * @since 3.0 + */ + public static final short SIGNAL_LOAD_SUB_BRANCHES = 32; - public static final short SIGNAL_REMOTE_SESSION_NOTIFICATION = 32; + /** + * @since 3.0 + */ + public static final short SIGNAL_BRANCH_NOTIFICATION = 33; // ////////////////////////////////////////////////////////////////////// // Session Management @@ -99,11 +129,6 @@ public interface CDOProtocolConstants public static final int ERROR_NO_SESSION = -2; // ////////////////////////////////////////////////////////////////////// - // View Management - - public static final byte VIEW_CLOSED = -1; - - // ////////////////////////////////////////////////////////////////////// // Query Support public static final String QUERY_LANGUAGE_RESOURCES = "resources"; //$NON-NLS-1$ diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java index 24e6930b08..aa4d816445 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevision.java @@ -11,7 +11,8 @@ */ package org.eclipse.emf.cdo.common.revision; -import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.ecore.EClass; @@ -19,14 +20,17 @@ import org.eclipse.emf.ecore.EClass; /** * @author Eike Stepper */ -public interface CDORevision +public interface CDORevision extends CDORevisionKey, CDOBranchPoint { - public static final long UNSPECIFIED_DATE = 0; + /** + * @since 3.0 + */ + public static final int MAIN_BRANCH_ID = CDOBranch.MAIN_BRANCH_ID; /** - * @since 2.0 + * @since 3.0 */ - public static final int UNSPECIFIED_VERSION = 0; + public static final int FIRST_VERSION = 1; public static final int UNCHUNKED = -1; @@ -45,25 +49,20 @@ public interface CDORevision */ public EClass getEClass(); - public CDOID getID(); - - // /** - // * @since 3.0 - // */ - // public int getBranchID(); - public int getVersion(); - public long getCreated(); - public long getRevised(); - public boolean isCurrent(); + /** + * Returns <code>true</code> exactly if {@link #getTimeStamp()} does not return {@link #UNSPECIFIED_DATE}, + * <code>false</code> otherwise. + * + * @since 3.0 + */ + public boolean isHistorical(); public boolean isValid(long timeStamp); - public boolean isTransactional(); - /** * @since 2.0 */ diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionKey.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionKey.java new file mode 100644 index 0000000000..7d1de6474c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionKey.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2004 - 2009 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.common.revision; + +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface CDORevisionKey extends CDOBranchVersion +{ + public CDOID getID(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionManager.java index ca83e0c0a9..0ddc4a67ef 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionManager.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionManager.java @@ -10,11 +10,12 @@ */ package org.eclipse.emf.cdo.common.revision; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.ecore.EClass; -import java.util.Collection; import java.util.List; /** @@ -28,28 +29,16 @@ public interface CDORevisionManager */ public EClass getObjectType(CDOID id); - public boolean containsRevision(CDOID id); + public boolean containsRevision(CDOID id, CDOBranchPoint branchPoint); - public boolean containsRevisionByTime(CDOID id, long timeStamp); - - public boolean containsRevisionByVersion(CDOID id, int version); - - public CDORevision getRevision(CDOID id, int referenceChunk, int prefetchDepth); - - public CDORevision getRevision(CDOID id, int referenceChunk, int prefetchDepth, boolean loadOnDemand); - - public CDORevision getRevisionByTime(CDOID id, int referenceChunk, int prefetchDepth, long timeStamp); - - public CDORevision getRevisionByTime(CDOID id, int referenceChunk, int prefetchDepth, long timeStamp, + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, boolean loadOnDemand); - public CDORevision getRevisionByVersion(CDOID id, int referenceChunk, int prefetchDepth, int version); - - public CDORevision getRevisionByVersion(CDOID id, int referenceChunk, int prefetchDepth, int version, - boolean loadOnDemand); + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, + int prefetchDepth, boolean loadOnDemand); - public List<CDORevision> getRevisions(Collection<CDOID> ids, int referenceChunk, int prefetchDepth); + public boolean containsRevisionByVersion(CDOID id, CDOBranchVersion branchVersion); - public List<CDORevision> getRevisionsByTime(Collection<CDOID> ids, int referenceChunk, int prefetchDepth, - long timeStamp, boolean loadOnDemand); + public CDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk, + boolean loadOnDemand); } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java index fdb12488f8..39ed880b3a 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/CDORevisionUtil.java @@ -10,16 +10,24 @@ */ package org.eclipse.emf.cdo.common.revision; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDTemp; import org.eclipse.emf.cdo.internal.common.messages.Messages; import org.eclipse.emf.cdo.internal.common.revision.CDOFeatureMapEntryImpl; import org.eclipse.emf.cdo.internal.common.revision.CDORevisionImpl; +import org.eclipse.emf.cdo.internal.common.revision.CDORevisionKeyImpl; import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureMapEntry; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.FeatureMap; +import java.io.PrintStream; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import java.util.Map; /** @@ -34,6 +42,22 @@ public final class CDORevisionUtil } /** + * @since 3.0 + */ + public static CDORevisionKey createRevisionKey(CDOID id, CDOBranch branch, int version) + { + return new CDORevisionKeyImpl(id, branch, version); + } + + /** + * @since 3.0 + */ + public static CDORevisionKey createRevisionKey(CDORevisionKey source) + { + return new CDORevisionKeyImpl(source.getID(), source.getBranch(), source.getVersion()); + } + + /** * @since 2.0 */ public static FeatureMap.Entry createFeatureMapEntry(EStructuralFeature feature, Object value) @@ -57,15 +81,59 @@ public final class CDORevisionUtil /** * @since 3.0 */ - public static int getOriginalVersion(CDORevision revision) + public static void dumpAllRevisions(Map<CDOBranch, List<CDORevision>> map, PrintStream out) { - int version = revision.getVersion(); - if (revision.isTransactional()) + final int pad = 48; + ArrayList<CDOBranch> branches = new ArrayList<CDOBranch>(map.keySet()); + Collections.sort(branches); + + for (CDOBranch branch : branches) + { + out.println(padTimeRange(branch.getName() + "[" + branch.getID() + "]", pad, branch.getBase().getTimeStamp(), + CDORevision.UNSPECIFIED_DATE)); + + List<CDORevision> revisions = map.get(branch); + Collections.sort(revisions, new Comparator<CDORevision>() + { + public int compare(CDORevision rev1, CDORevision rev2) + { + int result = rev1.getID().compareTo(rev2.getID()); + if (result == 0) + { + int version1 = rev1.getVersion(); + int version2 = rev2.getVersion(); + result = version1 < version2 ? -1 : version1 == version2 ? 0 : 1; + } + + return result; + } + }); + + for (CDORevision revision : revisions) + { + out.println(padTimeRange(" " + revision, pad, revision.getTimeStamp(), revision.getRevised())); + } + + out.println(); + } + } + + private static String padTimeRange(String s, int pos, long t1, long t2) + { + StringBuffer buffer = new StringBuffer(s); + while (buffer.length() < pos) + { + buffer.append(' '); + } + + String revised = "*"; + if (t2 != CDORevision.UNSPECIFIED_DATE) { - --version; + revised = MessageFormat.format("{0,date} {0,time,HH:mm:ss:SSS}", t2); } - return version; + buffer.append(MessageFormat.format("{0,date} {0,time,HH:mm:ss:SSS}/{1}", t1, revised)); + return buffer.toString(); } /** diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCache.java index e19f77ebc0..cf81bf809c 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCache.java @@ -10,8 +10,12 @@ */ package org.eclipse.emf.cdo.common.revision.cache; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.internal.common.revision.cache.mem.MEMRevisionCache; import org.eclipse.emf.cdo.internal.common.revision.cache.noop.NOOPRevisionCache; import org.eclipse.net4j.util.event.IEvent; @@ -25,62 +29,50 @@ import java.util.List; * @author Eike Stepper * @since 2.0 */ -public interface CDORevisionCache extends INotifier, CDORevisionCacheAdder +public interface CDORevisionCache extends INotifier { /** * @since 3.0 */ public static final CDORevisionCache NOOP = NOOPRevisionCache.INSTANCE; - public EClass getObjectType(CDOID id); - /** * @since 3.0 */ - public CDORevision getRevision(CDOID id); + public boolean isSupportingBranches(); - /** - * @since 3.0 - */ - public CDORevision getRevisionByTime(CDOID id, long timeStamp); - - /** - * @since 3.0 - */ - public CDORevision getRevisionByVersion(CDOID id, int version); + public EClass getObjectType(CDOID id); /** * @since 3.0 */ - public void removeRevision(CDORevision revision); + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint); /** * @since 3.0 */ - public CDORevision removeRevision(CDOID id, int version); + public CDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion); /** * Returns a list of {@link CDORevision revisions} that are current. + * + * @since 3.0 */ - public List<CDORevision> getRevisions(); - - public void clear(); + public List<CDORevision> getCurrentRevisions(); /** * @author Eike Stepper */ - public interface EvictionEvent extends IEvent + public interface EvictionEvent extends IEvent, CDORevisionKey { /** * @since 3.0 */ public CDORevisionCache getSource(); - public CDOID getID(); - - public int getVersion(); - /** + * May be <code>null</code> for certain cache implementations, e.g. {@link MEMRevisionCache}. + * * @since 3.0 */ public CDORevision getRevision(); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCacheFactory.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCacheFactory.java new file mode 100644 index 0000000000..a42f133f60 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCacheFactory.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2004 - 2009 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.common.revision.cache; + +import org.eclipse.emf.cdo.common.revision.CDORevision; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface CDORevisionCacheFactory +{ + public CDORevisionCache createRevisionCache(CDORevision revision); + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static class PrototypeInstantiator implements CDORevisionCacheFactory + { + private CDORevisionCache prototype; + + public PrototypeInstantiator(CDORevisionCache prototype) + { + this.prototype = prototype; + } + + public CDORevisionCache getPrototype() + { + return prototype; + } + + public CDORevisionCache createRevisionCache(CDORevision revision) + { + if (revision.getBranch().isMainBranch()) + { + return prototype; + } + + return ((InternalCDORevisionCache)prototype).instantiate(revision); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCacheUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCacheUtil.java index 1df3b1202e..a5b3011d5e 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCacheUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/CDORevisionCacheUtil.java @@ -4,12 +4,14 @@ * 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.common.revision.cache; +import org.eclipse.emf.cdo.internal.common.revision.cache.branch.BranchDispatcher; +import org.eclipse.emf.cdo.internal.common.revision.cache.branch.BranchRevisionCache; import org.eclipse.emf.cdo.internal.common.revision.cache.lru.LRURevisionCache; import org.eclipse.emf.cdo.internal.common.revision.cache.mem.MEMRevisionCache; import org.eclipse.emf.cdo.internal.common.revision.cache.two.TwoLevelRevisionCache; @@ -54,8 +56,42 @@ public final class CDORevisionCacheUtil public static CDORevisionCache createTwoLevelCache(CDORevisionCache level1, CDORevisionCache level2) { TwoLevelRevisionCache cache = new TwoLevelRevisionCache(); - cache.setLevel1(level1); - cache.setLevel2(level2); + cache.setLevel1((InternalCDORevisionCache)level1); + cache.setLevel2((InternalCDORevisionCache)level2); + return cache; + } + + /** + * Creates and returns a new memory sensitive revision cache that supports branches. + * + * @since 3.0 + */ + public static CDORevisionCache createBranchRevisionCache() + { + return new BranchRevisionCache(); + } + + /** + * Creates and returns a new branch dispatcher cache. + * + * @since 3.0 + */ + public static CDORevisionCache createBranchDispatcher(CDORevisionCacheFactory factory) + { + BranchDispatcher cache = new BranchDispatcher(); + cache.setFactory(factory); + return cache; + } + + /** + * Creates and returns a new branch dispatcher cache. + * + * @since 3.0 + */ + public static CDORevisionCache createBranchDispatcher(CDORevisionCache protoType) + { + BranchDispatcher cache = new BranchDispatcher(); + cache.setFactory(new CDORevisionCacheFactory.PrototypeInstantiator(protoType)); return cache; } @@ -69,12 +105,19 @@ public final class CDORevisionCacheUtil } /** - * Identical to calling - * <p> - * <code>{@link #createDefaultCache(int, int) createDefaultCache}({@link #DEFAULT_CAPACITY_CURRENT}, {@link #DEFAULT_CAPACITY_REVISED})</code> + * Identical to calling {@link #createBranchRevisionCache() createBranchRevisionCache()} if + * <code>supportingBranches</code> is <code>true</code>, {@link #createDefaultCache(int, int) + * createDefaultCache(DEFAULT_CAPACITY_CURRENT, DEFAULT_CAPACITY_REVISED)} otherwise. + * + * @since 3.0 */ - public static CDORevisionCache createDefaultCache() + public static CDORevisionCache createDefaultCache(boolean supportingBranches) { - return createDefaultCache(DEFAULT_CAPACITY_CURRENT, DEFAULT_CAPACITY_REVISED); + // if (supportingBranches) + { + return createBranchRevisionCache(); + } + + // return createDefaultCache(DEFAULT_CAPACITY_CURRENT, DEFAULT_CAPACITY_REVISED); } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/InternalCDORevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/InternalCDORevisionCache.java new file mode 100644 index 0000000000..4ce55acf25 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/cache/InternalCDORevisionCache.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2004 - 2009 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.common.revision.cache; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; + +import org.eclipse.net4j.util.lifecycle.ILifecycle; + +import java.util.List; +import java.util.Map; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface InternalCDORevisionCache extends CDORevisionCache, ILifecycle +{ + public InternalCDORevisionCache instantiate(CDORevision revision); + + public boolean addRevision(CDORevision revision); + + public CDORevision removeRevision(CDOID id, CDOBranchVersion branchVersion); + + public void clear(); + + public Map<CDOBranch, List<CDORevision>> getAllRevisions(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/delta/CDORevisionDelta.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/delta/CDORevisionDelta.java index 2615adfbb1..0952086524 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/delta/CDORevisionDelta.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/revision/delta/CDORevisionDelta.java @@ -11,8 +11,8 @@ */ package org.eclipse.emf.cdo.common.revision.delta; -import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionKey; import org.eclipse.emf.ecore.EClass; @@ -22,25 +22,13 @@ import java.util.List; * @author Eike Stepper * @noimplement This interface is not intended to be implemented by clients. */ -public interface CDORevisionDelta +public interface CDORevisionDelta extends CDORevisionKey { - public CDOID getID(); - /** * @since 3.0 */ public EClass getEClass(); - /** - * Specify the version of the object BEFORE it was modified. - */ - public int getOriginVersion(); - - /** - * Specify the version of the object AFTER it was modified. - */ - public int getDirtyVersion(); - public List<CDOFeatureDelta> getFeatureDeltas(); public void apply(CDORevision revision); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchImpl.java new file mode 100644 index 0000000000..d2bf275576 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchImpl.java @@ -0,0 +1,276 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.branch; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; +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.branch.InternalCDOBranchManager.BranchLoader.BranchInfo; +import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader.SubBranchInfo; + +import java.text.MessageFormat; + +/** + * @author Eike Stepper + */ +public class CDOBranchImpl implements InternalCDOBranch +{ + public static final int ILLEGAL_BRANCH_ID = Integer.MIN_VALUE; + + private int id; + + private String name; + + private Object baseOrBranchManager; + + private CDOBranchPoint head; + + private InternalCDOBranch[] branches; + + public CDOBranchImpl(int id, String name, CDOBranchPoint base) + { + this.id = id; + this.name = name; + baseOrBranchManager = base; + head = CDOBranchUtil.createBranchPoint(this, CDOBranchPoint.UNSPECIFIED_DATE); + } + + public CDOBranchImpl(int id, InternalCDOBranchManager branchManager) + { + this.id = id; + baseOrBranchManager = branchManager; + } + + public boolean isMainBranch() + { + return false; + } + + public InternalCDOBranchManager getBranchManager() + { + if (isProxy()) + { + return (InternalCDOBranchManager)baseOrBranchManager; + } + + CDOBranchPoint base = (CDOBranchPoint)baseOrBranchManager; + return (InternalCDOBranchManager)base.getBranch().getBranchManager(); + } + + public int getID() + { + return id; + } + + public String getName() + { + loadIfNeeded(); + return name; + } + + public boolean isProxy() + { + return name == null; + } + + public CDOBranchPoint getBase() + { + loadIfNeeded(); + return (CDOBranchPoint)baseOrBranchManager; + } + + public CDOBranchPoint getHead() + { + return head; + } + + public CDOBranchPoint getPoint(long timeStamp) + { + return CDOBranchUtil.createBranchPoint(this, timeStamp); + } + + public CDOBranchVersion getVersion(int version) + { + return CDOBranchUtil.createBranchVersion(this, version); + } + + public InternalCDOBranch createBranch(String name, long timeStamp) + { + return getBranchManager().createBranch(name, this, timeStamp); + } + + public InternalCDOBranch createBranch(String name) + { + return getBranchManager().createBranch(name, this, CDOBranchPoint.UNSPECIFIED_DATE); + } + + public synchronized InternalCDOBranch[] getBranches() + { + loadIfNeeded(); + if (branches == null) + { + InternalCDOBranchManager branchManager = getBranchManager(); + SubBranchInfo[] infos = branchManager.getBranchLoader().loadSubBranches(id); + branches = new InternalCDOBranch[infos.length]; + for (int i = 0; i < infos.length; i++) + { + SubBranchInfo info = infos[i]; + branches[i] = branchManager.getBranch(info.getID(), info.getName(), info.getBaseTimeStamp(), this); + } + } + + return branches; + } + + public InternalCDOBranch getBranch(String path) + { + while (path.endsWith(PATH_SEPARATOR)) + { + path = path.substring(0, path.length() - PATH_SEPARATOR.length()); + } + + int sep = path.indexOf(PATH_SEPARATOR); + if (sep == -1) + { + return getChild(path); + } + + String name = path.substring(0, sep); + InternalCDOBranch child = getChild(name); + + // Recurse + String rest = path.substring(sep + 1); + return child.getBranch(rest); + } + + private InternalCDOBranch getChild(String name) + { + InternalCDOBranch[] branches = getBranches(); + for (InternalCDOBranch branch : branches) + { + if (name.equals(branch.getName())) + { + return branch; + } + } + + return null; + } + + public BranchInfo getBranchInfo() + { + CDOBranchPoint base = getBase(); + return new BranchInfo(getName(), base.getBranch().getID(), base.getTimeStamp()); + } + + public void setBranchInfo(String name, InternalCDOBranch baseBranch, long baseTimeStamp) + { + this.name = name; + baseOrBranchManager = CDOBranchUtil.createBranchPoint(baseBranch, baseTimeStamp); + } + + public synchronized void addChild(InternalCDOBranch branch) + { + if (branches == null) + { + branches = new InternalCDOBranch[] { branch }; + } + else + { + InternalCDOBranch[] newBranches = new InternalCDOBranch[branches.length + 1]; + System.arraycopy(branches, 0, newBranches, 0, branches.length); + newBranches[branches.length] = branch; + branches = newBranches; + } + } + + public int compareTo(CDOBranch o) + { + int otherID = o.getID(); + return id < otherID ? -1 : id == otherID ? 0 : 1; + } + + @Override + public int hashCode() + { + return id; + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (obj instanceof CDOBranch) + { + CDOBranch that = (CDOBranch)obj; + return id == that.getID(); + } + + return false; + } + + @Override + public String toString() + { + if (isProxy()) + { + return MessageFormat.format("Branch[id={0}, PROXY]", id); + } + + return MessageFormat.format("Branch[id={0}, name={1}]", id, name); + } + + private synchronized void loadIfNeeded() + { + if (isProxy()) + { + InternalCDOBranchManager branchManager = (InternalCDOBranchManager)baseOrBranchManager; + BranchInfo branchInfo = branchManager.getBranchLoader().loadBranch(id); + + CDOBranch baseBranch = branchManager.getBranch(branchInfo.getBaseBranchID()); + name = branchInfo.getName(); + baseOrBranchManager = CDOBranchUtil.createBranchPoint(baseBranch, branchInfo.getBaseTimeStamp()); + } + } + + /** + * @author Eike Stepper + */ + public static class Main extends CDOBranchImpl + { + private InternalCDOBranchManager branchManager; + + public Main(InternalCDOBranchManager branchManager, long timeStamp) + { + super(MAIN_BRANCH_ID, MAIN_BRANCH_NAME, CDOBranchUtil.createBranchPoint(null, timeStamp)); + this.branchManager = branchManager; + } + + @Override + public boolean isMainBranch() + { + return true; + } + + @Override + public InternalCDOBranchManager getBranchManager() + { + return branchManager; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java new file mode 100644 index 0000000000..64ae67e932 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchManagerImpl.java @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.branch; + +import org.eclipse.emf.cdo.common.CDOTimeProvider; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchCreatedEvent; +import org.eclipse.emf.cdo.common.branch.CDOBranchManager; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; +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.branch.InternalCDOBranchManager.BranchLoader.BranchInfo; + +import org.eclipse.net4j.util.event.Event; +import org.eclipse.net4j.util.lifecycle.Lifecycle; +import org.eclipse.net4j.util.ref.ReferenceValueMap; +import org.eclipse.net4j.util.ref.ReferenceValueMap.Soft; + +import java.util.Map; + +/** + * @author Eike Stepper + */ +public class CDOBranchManagerImpl extends Lifecycle implements InternalCDOBranchManager +{ + private BranchLoader branchLoader; + + private CDOTimeProvider timeProvider; + + private InternalCDOBranch mainBranch; + + private Map<Integer, InternalCDOBranch> branches = createMap(); + + public CDOBranchManagerImpl() + { + } + + public BranchLoader getBranchLoader() + { + return branchLoader; + } + + public void setBranchLoader(BranchLoader branchLoader) + { + checkInactive(); + this.branchLoader = branchLoader; + } + + public CDOTimeProvider getTimeProvider() + { + return timeProvider; + } + + public void setTimeProvider(CDOTimeProvider timeProvider) + { + this.timeProvider = timeProvider; + } + + public void initMainBranch(long repositoryCreationTime) + { + checkInactive(); + mainBranch = new CDOBranchImpl.Main(this, repositoryCreationTime); + } + + public void handleBranchCreated(InternalCDOBranch branch) + { + CDOBranchPoint base = branch.getBase(); + InternalCDOBranch baseBranch = (InternalCDOBranch)base.getBranch(); + baseBranch.addChild(branch); + + fireEvent(new BranchCreatedEvent(branch)); + } + + public InternalCDOBranch getMainBranch() + { + checkActive(); + return mainBranch; + } + + public InternalCDOBranch getBranch(int branchID) + { + checkActive(); + if (branchID == CDOBranch.MAIN_BRANCH_ID) + { + return mainBranch; + } + + InternalCDOBranch branch; + synchronized (branches) + { + branch = branches.get(branchID); + if (branch == null) + { + branch = new CDOBranchImpl(branchID, this); + putBranch(branch); + } + } + + return branch; + } + + public InternalCDOBranch getBranch(int id, String name, long baseTimeStamp, InternalCDOBranch base) + { + synchronized (branches) + { + InternalCDOBranch branch = branches.get(id); + if (branch == null) + { + branch = new CDOBranchImpl(id, name, CDOBranchUtil.createBranchPoint(base, baseTimeStamp)); + putBranch(branch); + } + else if (branch.isProxy()) + { + branch.setBranchInfo(name, base, baseTimeStamp); + } + + return branch; + } + } + + public InternalCDOBranch getBranch(String path) + { + int sep = path.indexOf(CDOBranch.PATH_SEPARATOR); + if (sep == -1) + { + if (CDOBranch.MAIN_BRANCH_NAME.equals(path)) + { + return mainBranch; + } + + return null; + } + + String name = path.substring(0, sep); + if (CDOBranch.MAIN_BRANCH_NAME.equals(name)) + { + String rest = path.substring(sep + 1); + return mainBranch.getBranch(rest); + } + + return null; + } + + public InternalCDOBranch createBranch(String name, InternalCDOBranch baseBranch, long baseTimeStamp) + { + checkActive(); + + if (baseTimeStamp == CDOBranchPoint.UNSPECIFIED_DATE) + { + baseTimeStamp = timeProvider.getTimeStamp(); + } + + int branchID = branchLoader.createBranch(new BranchInfo(name, baseBranch.getID(), baseTimeStamp)); + CDOBranchPoint base = CDOBranchUtil.createBranchPoint(baseBranch, baseTimeStamp); + InternalCDOBranch branch = new CDOBranchImpl(branchID, name, base); + synchronized (branches) + { + putBranch(branch); + } + + handleBranchCreated(branch); + return branch; + } + + /** + * {@link #branches} must be synchronized by caller! + */ + private boolean putBranch(InternalCDOBranch branch) + { + int id = branch.getID(); + if (branches.containsKey(id)) + { + return false; + } + + branches.put(id, branch); + return true; + } + + protected Soft<Integer, InternalCDOBranch> createMap() + { + return new ReferenceValueMap.Soft<Integer, InternalCDOBranch>(); + } + + @Override + protected void doBeforeActivate() throws Exception + { + super.doBeforeActivate(); + checkNull(branchLoader, "branchLoader"); + checkNull(timeProvider, "timeProvider"); + checkNull(mainBranch, "mainBranch"); + } + + /** + * @author Eike Stepper + */ + private static final class BranchCreatedEvent extends Event implements CDOBranchCreatedEvent + { + private static final long serialVersionUID = 1L; + + private CDOBranch branch; + + public BranchCreatedEvent(CDOBranch branch) + { + super(branch.getBranchManager()); + this.branch = branch; + } + + @Override + public CDOBranchManager getSource() + { + return (CDOBranchManager)super.getSource(); + } + + public CDOBranch getBranch() + { + return branch; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchPointImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchPointImpl.java new file mode 100644 index 0000000000..6de4e1df9f --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchPointImpl.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.branch; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; + +import java.text.MessageFormat; + +/** + * @author Eike Stepper + */ +public class CDOBranchPointImpl implements CDOBranchPoint +{ + private CDOBranch branch; + + private long timeStamp; + + public CDOBranchPointImpl(CDOBranch branch, long timeStamp) + { + this.branch = branch; + this.timeStamp = timeStamp; + } + + public CDOBranch getBranch() + { + return branch; + } + + public long getTimeStamp() + { + return timeStamp; + } + + public int compareTo(CDOBranchPoint o) + { + int result = branch.compareTo(o.getBranch()); + if (result == 0) + { + long timeStamp2 = o.getTimeStamp(); + result = timeStamp < timeStamp2 ? -1 : timeStamp == timeStamp2 ? 0 : 1; + } + + return result; + } + + @Override + public int hashCode() + { + return branch.hashCode() ^ new Long(timeStamp).hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (obj instanceof CDOBranchPoint) + { + CDOBranchPoint that = (CDOBranchPoint)obj; + return branch.equals(that.getBranch()) && timeStamp == that.getTimeStamp(); + } + + return false; + } + + @Override + public String toString() + { + return MessageFormat.format("BranchPoint[{0}, {1,date} {1,time,HH:mm:ss:SSS}]", branch, timeStamp); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchVersionImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchVersionImpl.java new file mode 100644 index 0000000000..4482c2bb2c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/branch/CDOBranchVersionImpl.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.branch; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; + +import java.text.MessageFormat; + +/** + * @author Eike Stepper + */ +public class CDOBranchVersionImpl implements CDOBranchVersion +{ + private CDOBranch branch; + + private int version; + + public CDOBranchVersionImpl(CDOBranch branch, int version) + { + this.branch = branch; + this.version = version; + } + + public CDOBranch getBranch() + { + return branch; + } + + public int getVersion() + { + return version; + } + + @Override + public int hashCode() + { + return branch.hashCode() ^ version; + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (obj instanceof CDOBranchVersion) + { + CDOBranchVersion that = (CDOBranchVersion)obj; + return branch.equals(that.getBranch()) && version == that.getVersion(); + } + + return false; + } + + @Override + public String toString() + { + return MessageFormat.format("BranchVersion[{0}, v{1}]", branch, version); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/commit/CDOCommitImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/commit/CDOCommitImpl.java new file mode 100644 index 0000000000..89c1a7033e --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/commit/CDOCommitImpl.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.commit; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.commit.CDOCommit; +import org.eclipse.emf.cdo.internal.common.branch.CDOBranchPointImpl; + +/** + * @author Eike Stepper + */ +public class CDOCommitImpl extends CDOBranchPointImpl implements CDOCommit +{ + private String userID; + + private String comment; + + public CDOCommitImpl(CDOBranch branch, long timeStamp, String userID, String comment) + { + super(branch, timeStamp); + this.userID = userID; + this.comment = comment; + } + + public String getUserID() + { + return userID; + } + + public String getComment() + { + return comment; + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndBranchImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndBranchImpl.java new file mode 100644 index 0000000000..6ab18f3155 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndBranchImpl.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.id; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDAndBranch; +import org.eclipse.emf.cdo.common.io.CDODataInput; +import org.eclipse.emf.cdo.common.io.CDODataOutput; + +import java.io.IOException; +import java.text.MessageFormat; + +/** + * @author Eike Stepper + */ +public class CDOIDAndBranchImpl implements CDOIDAndBranch +{ + private CDOID id; + + private CDOBranch branch; + + public CDOIDAndBranchImpl(CDOID id, CDOBranch branch) + { + this.id = id; + this.branch = branch; + } + + public CDOIDAndBranchImpl(CDODataInput in) throws IOException + { + id = in.readCDOID(); + branch = in.readCDOBranch(); + } + + public void write(CDODataOutput out) throws IOException + { + out.writeCDOID(id); + out.writeCDOBranch(branch); + } + + public CDOID getID() + { + return id; + } + + public CDOBranch getBranch() + { + return branch; + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (obj instanceof CDOIDAndBranch) + { + CDOIDAndBranch that = (CDOIDAndBranch)obj; + return id.equals(that.getID()) && branch.equals(that.getBranch()); + } + + return false; + } + + @Override + public int hashCode() + { + return id.hashCode() ^ branch.hashCode(); + } + + @Override + public String toString() + { + return MessageFormat.format("{0}:{1}", id, branch.getID()); //$NON-NLS-1$ + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndVersionAndBranchImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndVersionAndBranchImpl.java new file mode 100644 index 0000000000..45561844a7 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndVersionAndBranchImpl.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.id; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDAndVersionAndBranch; +import org.eclipse.emf.cdo.common.io.CDODataInput; +import org.eclipse.emf.cdo.common.io.CDODataOutput; + +import java.io.IOException; +import java.text.MessageFormat; + +/** + * @author Eike Stepper + */ +public final class CDOIDAndVersionAndBranchImpl extends CDOIDAndVersionImpl implements CDOIDAndVersionAndBranch +{ + private int branchID; + + public CDOIDAndVersionAndBranchImpl(CDOID id, int version, int branchID) + { + super(id, version); + this.branchID = branchID; + } + + public CDOIDAndVersionAndBranchImpl(CDODataInput in) throws IOException + { + super(in); + branchID = in.readInt(); + } + + @Override + public void write(CDODataOutput out) throws IOException + { + super.write(out); + out.writeInt(branchID); + } + + public int getBranchID() + { + return branchID; + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (obj instanceof CDOIDAndVersionAndBranch) + { + CDOIDAndVersionAndBranch that = (CDOIDAndVersionAndBranch)obj; + return getID().equals(that.getID()) && getVersion() == that.getVersion() && branchID == that.getBranchID(); + } + + return false; + } + + @Override + public int hashCode() + { + return getID().hashCode() ^ getVersion() ^ branchID; + } + + @Override + public String toString() + { + return MessageFormat.format("{0}v{1}b{2}", getID(), getVersion(), branchID); //$NON-NLS-1$ + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndVersionImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndVersionImpl.java index 67f9874b45..2a26ff154e 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndVersionImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/id/CDOIDAndVersionImpl.java @@ -4,7 +4,7 @@ * 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 */ @@ -21,7 +21,7 @@ import java.text.MessageFormat; /** * @author Eike Stepper */ -public final class CDOIDAndVersionImpl implements CDOIDAndVersion +public class CDOIDAndVersionImpl implements CDOIDAndVersion { private CDOID id; diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataInputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataInputImpl.java index 89931de7b3..bbe18c6bc4 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataInputImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataInputImpl.java @@ -11,8 +11,14 @@ */ package org.eclipse.emf.cdo.internal.common.io; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchManager; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDAndVersion; +import org.eclipse.emf.cdo.common.id.CDOIDAndVersionAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDMetaRange; import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.id.CDOID.Type; @@ -31,6 +37,8 @@ import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.internal.common.bundle.OM; +import org.eclipse.emf.cdo.internal.common.id.CDOIDAndBranchImpl; +import org.eclipse.emf.cdo.internal.common.id.CDOIDAndVersionAndBranchImpl; import org.eclipse.emf.cdo.internal.common.id.CDOIDAndVersionImpl; import org.eclipse.emf.cdo.internal.common.id.CDOIDExternalImpl; import org.eclipse.emf.cdo.internal.common.id.CDOIDMetaImpl; @@ -49,6 +57,7 @@ import org.eclipse.emf.cdo.internal.common.revision.delta.CDORemoveFeatureDeltaI import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl; import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl; import org.eclipse.emf.cdo.internal.common.revision.delta.CDOUnsetFeatureDeltaImpl; +import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; import org.eclipse.emf.cdo.spi.common.id.AbstractCDOID; import org.eclipse.emf.cdo.spi.common.id.InternalCDOIDObject; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo; @@ -147,6 +156,26 @@ public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating impl return CDOModelUtil.getType(typeID); } + public CDOBranch readCDOBranch() throws IOException + { + int branchID = readInt(); + return getBranchManager().getBranch(branchID); + } + + public CDOBranchPoint readCDOBranchPoint() throws IOException + { + CDOBranch branch = readCDOBranch(); + long timeStamp = readLong(); + return CDOBranchUtil.createBranchPoint(branch, timeStamp); + } + + public CDOBranchVersion readCDOBranchVersion() throws IOException + { + CDOBranch branch = readCDOBranch(); + int version = readInt(); + return CDOBranchUtil.createBranchVersion(branch, version); + } + public CDOID readCDOID() throws IOException { byte ordinal = readByte(); @@ -239,6 +268,16 @@ public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating impl return new CDOIDAndVersionImpl(this); } + public CDOIDAndBranch readCDOIDAndBranch() throws IOException + { + return new CDOIDAndBranchImpl(this); + } + + public CDOIDAndVersionAndBranch readCDOIDAndVersionAndBranch() throws IOException + { + return new CDOIDAndVersionAndBranchImpl(this); + } + public CDOIDMetaRange readCDOIDMetaRange() throws IOException { boolean exist = readBoolean(); @@ -394,6 +433,8 @@ public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating impl protected abstract CDOPackageRegistry getPackageRegistry(); + protected abstract CDOBranchManager getBranchManager(); + protected abstract CDORevisionFactory getRevisionFactory(); protected abstract CDOListFactory getListFactory(); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataOutputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataOutputImpl.java index d6fc4bbbfb..a6c31da81b 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataOutputImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/io/CDODataOutputImpl.java @@ -10,8 +10,13 @@ */ package org.eclipse.emf.cdo.internal.common.io; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDAndVersion; +import org.eclipse.emf.cdo.common.id.CDOIDAndVersionAndBranch; import org.eclipse.emf.cdo.common.id.CDOIDMetaRange; import org.eclipse.emf.cdo.common.id.CDOIDProvider; import org.eclipse.emf.cdo.common.io.CDODataOutput; @@ -26,6 +31,8 @@ import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.internal.common.bundle.OM; +import org.eclipse.emf.cdo.internal.common.id.CDOIDAndBranchImpl; +import org.eclipse.emf.cdo.internal.common.id.CDOIDAndVersionAndBranchImpl; import org.eclipse.emf.cdo.internal.common.id.CDOIDAndVersionImpl; import org.eclipse.emf.cdo.internal.common.messages.Messages; import org.eclipse.emf.cdo.internal.common.model.CDOTypeImpl; @@ -115,6 +122,23 @@ public abstract class CDODataOutputImpl extends ExtendedDataOutput.Delegating im ((CDOTypeImpl)cdoType).write(this); } + public void writeCDOBranch(CDOBranch branch) throws IOException + { + writeInt(branch.getID()); + } + + public void writeCDOBranchPoint(CDOBranchPoint branchPoint) throws IOException + { + writeCDOBranch(branchPoint.getBranch()); + writeLong(branchPoint.getTimeStamp()); + } + + public void writeCDOBranchVersion(CDOBranchVersion branchVersion) throws IOException + { + writeCDOBranch(branchVersion.getBranch()); + writeInt(branchVersion.getVersion()); + } + public void writeCDOID(CDOID id) throws IOException { if (id == null) @@ -155,6 +179,16 @@ public abstract class CDODataOutputImpl extends ExtendedDataOutput.Delegating im ((CDOIDAndVersionImpl)idAndVersion).write(this); } + public void writeCDOIDAndBranch(CDOIDAndBranch idAndBranch) throws IOException + { + ((CDOIDAndBranchImpl)idAndBranch).write(this); + } + + public void writeCDOIDAndVersionAndBranch(CDOIDAndVersionAndBranch idAndVersionAndBranch) throws IOException + { + ((CDOIDAndVersionAndBranchImpl)idAndVersionAndBranch).write(this); + } + public void writeCDOIDMetaRange(CDOIDMetaRange metaRange) throws IOException { if (metaRange == null) diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java index 6d2841c4a1..430ed1ff2c 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java @@ -4,7 +4,7 @@ * 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 */ @@ -311,7 +311,7 @@ public class CDOPackageUnitImpl implements InternalCDOPackageUnit @Override public String toString() { - String fmt = "CDOPackageUnit[id={0}, state={1}, type={2}, originalType={3}, timeStamp={4,date} {4,time}]"; //$NON-NLS-1$ + String fmt = "CDOPackageUnit[id={0}, state={1}, type={2}, originalType={3}, timeStamp={4,date} {4,time,HH:mm:ss:SSS}]"; //$NON-NLS-1$ return MessageFormat.format(fmt, getID(), getState(), getType(), getOriginalType(), getTimeStamp()); } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java index 59150b0aad..9d203962cb 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionImpl.java @@ -16,7 +16,7 @@ package org.eclipse.emf.cdo.internal.common.revision; import org.eclipse.emf.cdo.common.model.CDOModelUtil; import org.eclipse.emf.cdo.common.model.CDOType; import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.spi.common.revision.AbstractCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.BaseCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList; import org.eclipse.emf.ecore.EClass; @@ -26,7 +26,7 @@ import org.eclipse.emf.ecore.EStructuralFeature; /** * @author Eike Stepper */ -public class CDORevisionImpl extends AbstractCDORevision +public class CDORevisionImpl extends BaseCDORevision { private Object[] values; diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionKeyImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionKeyImpl.java new file mode 100644 index 0000000000..74f1e37c26 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionKeyImpl.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.revision; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.internal.common.branch.CDOBranchVersionImpl; + +import java.text.MessageFormat; + +/** + * @author Eike Stepper + */ +public class CDORevisionKeyImpl extends CDOBranchVersionImpl implements CDORevisionKey +{ + private CDOID id; + + public CDORevisionKeyImpl(CDOID id, CDOBranch branch, int version) + { + super(branch, version); + this.id = id; + } + + public CDOID getID() + { + return id; + } + + @Override + public int hashCode() + { + return id.hashCode() ^ super.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + + if (obj instanceof CDORevisionKey) + { + CDORevisionKey that = (CDORevisionKey)obj; + return id.equals(that.getID()) && getBranch().equals(that.getBranch()) && getVersion() == that.getVersion(); + } + + return false; + } + + @Override + public String toString() + { + return MessageFormat.format("{0}:{1}v{2}", id, getBranch().getID(), getVersion()); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java index a70df6d587..f36b718524 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/CDORevisionManagerImpl.java @@ -12,14 +12,23 @@ */ package org.eclipse.emf.cdo.internal.common.revision; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCacheUtil; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; import org.eclipse.emf.cdo.internal.common.bundle.OM; +import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; +import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; +import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo; +import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision; import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; import org.eclipse.net4j.util.lifecycle.Lifecycle; @@ -29,9 +38,10 @@ import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.emf.ecore.EClass; import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; /** * @author Eike Stepper @@ -40,24 +50,40 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, CDORevisionManagerImpl.class); + private boolean supportingBranches; + private RevisionLoader revisionLoader; private RevisionLocker revisionLocker; private CDORevisionFactory factory; - private CDORevisionCache cache; + private InternalCDORevisionCache cache; + + @ExcludeFromDump + private transient Object loadAndAddLock = new Object(); @ExcludeFromDump - private Object loadAndAddLock = new Object(); + private transient Object revisedLock = new Object(); @ExcludeFromDump - private Object revisedLock = new Object(); + private transient AtomicInteger loadCounterForTest; public CDORevisionManagerImpl() { } + public boolean isSupportingBranches() + { + return supportingBranches; + } + + public void setSupportingBranches(boolean on) + { + checkInactive(); + supportingBranches = on; + } + public RevisionLoader getRevisionLoader() { return revisionLoader; @@ -65,6 +91,7 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi public void setRevisionLoader(RevisionLoader revisionLoader) { + checkInactive(); this.revisionLoader = revisionLoader; } @@ -75,6 +102,7 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi public void setRevisionLocker(RevisionLocker revisionLocker) { + checkInactive(); this.revisionLocker = revisionLocker; } @@ -85,50 +113,51 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi public void setFactory(CDORevisionFactory factory) { + checkInactive(); this.factory = factory; } - public CDORevisionCache getCache() + public InternalCDORevisionCache getCache() { return cache; } public void setCache(CDORevisionCache cache) { - this.cache = cache; + checkInactive(); + this.cache = (InternalCDORevisionCache)cache; } - public boolean containsRevision(CDOID id) + public EClass getObjectType(CDOID id) { - return cache.getRevision(id) != null; + return cache.getObjectType(id); } - public boolean containsRevisionByTime(CDOID id, long timeStamp) + public boolean containsRevision(CDOID id, CDOBranchPoint branchPoint) { - return cache.getRevisionByTime(id, timeStamp) != null; - } + if (supportingBranches) + { + return getRevision(id, branchPoint, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, false, null) != null; + } - public boolean containsRevisionByVersion(CDOID id, int version) - { - return cache.getRevisionByVersion(id, version) != null; + return getCachedRevision(id, branchPoint) != null; } - public EClass getObjectType(CDOID id) + public boolean containsRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) { - return cache.getObjectType(id); + return cache.getRevisionByVersion(id, branchVersion) != null; } - public void reviseLatest(CDOID id) + public void reviseLatest(CDOID id, CDOBranch branch) { acquireAtomicRequestLock(revisedLock); try { - // TODO Consider CDORevisionCache.removeLatestRevision() - InternalCDORevision revision = (InternalCDORevision)cache.getRevision(id); + InternalCDORevision revision = (InternalCDORevision)cache.getRevision(id, branch.getHead()); if (revision != null) { - cache.removeRevision(revision.getID(), revision.getVersion()); + cache.removeRevision(id, branch.getVersion(revision.getVersion())); } } finally @@ -137,18 +166,18 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi } } - public void reviseVersion(CDOID id, int version, long timeStamp) + public void reviseVersion(CDOID id, CDOBranchVersion branchVersion, long timeStamp) { acquireAtomicRequestLock(revisedLock); try { - InternalCDORevision revision = (InternalCDORevision)cache.getRevisionByVersion(id, version); + InternalCDORevision revision = getCachedRevisionByVersion(id, branchVersion); if (revision != null) { if (timeStamp == CDORevision.UNSPECIFIED_DATE) { - cache.removeRevision(revision.getID(), revision.getVersion()); + cache.removeRevision(id, branchVersion); } else { @@ -162,39 +191,26 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi } } - public InternalCDORevision getRevision(CDOID id, int referenceChunk, int prefetchDepth) - { - return getRevision(id, referenceChunk, prefetchDepth, true); - } - - public InternalCDORevision getRevision(CDOID id, int referenceChunk, int prefetchDepth, boolean loadOnDemand) + public InternalCDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk, + boolean loadOnDemand) { + checkArg(branchVersion.getVersion() > 0, "Invalid version: " + branchVersion.getVersion()); acquireAtomicRequestLock(loadAndAddLock); try { - boolean prefetch = prefetchDepth != CDORevision.DEPTH_NONE; - InternalCDORevision revision = prefetch ? null : (InternalCDORevision)cache.getRevision(id); + InternalCDORevision revision = getCachedRevisionByVersion(id, branchVersion); if (revision == null) { if (loadOnDemand) { if (TRACER.isEnabled()) { - TRACER.format("Loading revision {0}", id); //$NON-NLS-1$ + TRACER.format("Loading revision {0} from {1}", id, branchVersion); //$NON-NLS-1$ } - revision = revisionLoader.loadRevision(id, referenceChunk, prefetchDepth); - addCachedRevisionIfNotNull(revision); - } - } - else - { - InternalCDORevision oldRevision = revision; - revision = verifyRevision(oldRevision, referenceChunk); - if (revision != oldRevision) - { - addCachedRevisionIfNotNull(revision); + revision = revisionLoader.loadRevisionByVersion(id, branchVersion, referenceChunk); + addRevision(revision); } } @@ -206,167 +222,193 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi } } - public InternalCDORevision getRevisionByTime(CDOID id, int referenceChunk, int prefetchDepth, long timeStamp) + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean loadOnDemand) { - return getRevisionByTime(id, referenceChunk, prefetchDepth, timeStamp, true); + return getRevision(id, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, null); } - public InternalCDORevision getRevisionByTime(CDOID id, int referenceChunk, int prefetchDepth, long timeStamp, - boolean loadOnDemand) + public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean loadOnDemand, SyntheticCDORevision[] synthetics) { - acquireAtomicRequestLock(loadAndAddLock); - - try - { - boolean prefetch = prefetchDepth != CDORevision.DEPTH_NONE; - InternalCDORevision revision = prefetch ? null : (InternalCDORevision)cache.getRevisionByTime(id, timeStamp); - if (revision == null || prefetchDepth != CDORevision.DEPTH_NONE) - { - if (loadOnDemand) - { - if (TRACER.isEnabled()) - { - TRACER.format("Loading revision {0} by time {1,date} {1,time}", id, timeStamp); //$NON-NLS-1$ - } + List<CDOID> ids = Collections.singletonList(id); + List<CDORevision> revisions = getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, + synthetics); + return (InternalCDORevision)revisions.get(0); + } - revision = revisionLoader.loadRevisionByTime(id, referenceChunk, prefetchDepth, timeStamp); - addCachedRevisionIfNotNull(revision); - } - } - else - { - InternalCDORevision verified = verifyRevision(revision, referenceChunk); - if (revision != verified) - { - addCachedRevisionIfNotNull(verified); - revision = verified; - } - } + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, + int prefetchDepth, boolean loadOnDemand) + { + return getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, null); + } - return revision; - } - finally + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, + int prefetchDepth, boolean loadOnDemand, SyntheticCDORevision[] synthetics) + { + RevisionInfo[] infos = new RevisionInfo[ids.size()]; + List<RevisionInfo> infosToLoad = createRevisionInfos(ids, branchPoint, loadOnDemand, infos); + if (infosToLoad != null) { - releaseAtomicRequestLock(loadAndAddLock); + loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth); } - } - public synchronized InternalCDORevision getRevisionByVersion(CDOID id, int referenceChunk, int prefetchDepth, - int version) - { - return getRevisionByVersion(id, referenceChunk, prefetchDepth, version, true); + return getResultsAndSynthetics(infos, synthetics); } - public InternalCDORevision getRevisionByVersion(CDOID id, int referenceChunk, int prefetchDepth, int version, - boolean loadOnDemand) + private List<RevisionInfo> createRevisionInfos(List<CDOID> ids, CDOBranchPoint branchPoint, boolean loadOnDemand, + RevisionInfo[] infos) { - acquireAtomicRequestLock(loadAndAddLock); - - try + List<RevisionInfo> infosToLoad = null; + Iterator<CDOID> idIterator = ids.iterator(); + for (int i = 0; i < infos.length; i++) { - boolean prefetch = prefetchDepth != CDORevision.DEPTH_NONE; - InternalCDORevision revision = prefetch ? null : (InternalCDORevision)cache.getRevisionByVersion(id, version); - if (revision == null) + CDOID id = idIterator.next(); + RevisionInfo info = createRevisionInfo(id, branchPoint); + infos[i] = info; + + if (info.isLoadNeeded() && loadOnDemand) { - if (loadOnDemand) + if (infosToLoad == null) { - if (TRACER.isEnabled()) - { - TRACER.format("Loading revision {0} by version {1}", id, version); //$NON-NLS-1$ - } - - revision = revisionLoader.loadRevisionByVersion(id, referenceChunk, prefetchDepth, version); - addCachedRevisionIfNotNull(revision); + infosToLoad = new ArrayList<RevisionInfo>(1); } + + infosToLoad.add(info); } + } - return revision; + return infosToLoad; + } + + private RevisionInfo createRevisionInfo(CDOID id, CDOBranchPoint branchPoint) + { + InternalCDORevision revision = getCachedRevision(id, branchPoint); + if (revision != null) + { + return createRevisionInfoAvailable(revision, branchPoint); } - finally + + if (supportingBranches) { - releaseAtomicRequestLock(loadAndAddLock); + revision = getCachedRevisionRecursively(id, branchPoint); + if (revision != null) + { + return createRevisionInfoAvailable(revision, branchPoint); + } } + + return createRevisionInfoMissing(id, branchPoint); } - public List<CDORevision> getRevisions(Collection<CDOID> ids, int referenceChunk, int prefetchDepth) + private RevisionInfo.Available createRevisionInfoAvailable(InternalCDORevision revision, + CDOBranchPoint requestedBranchPoint) { - List<CDOID> missingIDs = new ArrayList<CDOID>(0); - List<CDORevision> revisions = new ArrayList<CDORevision>(ids.size()); - for (CDOID id : ids) + if (revision instanceof PointerCDORevision) { - // TODO Combination of prefetch=true and loadOnDemand=false does not make sense! - InternalCDORevision revision = getRevision(id, referenceChunk, prefetchDepth, false); - revisions.add(revision); - if (revision == null) + PointerCDORevision pointer = (PointerCDORevision)revision; + CDOBranchVersion target = pointer.getTarget(); + InternalCDORevision targetRevision = target == null ? null : getCachedRevisionByVersion(pointer.getID(), target); + if (targetRevision != null) { - missingIDs.add(id); + target = targetRevision; } + + return new RevisionInfo.Available.Pointer(pointer.getID(), requestedBranchPoint, pointer, target); } - if (!missingIDs.isEmpty()) + if (revision instanceof DetachedCDORevision) { - acquireAtomicRequestLock(loadAndAddLock); - - try - { - List<InternalCDORevision> missingRevisions = revisionLoader.loadRevisions(missingIDs, referenceChunk, - prefetchDepth); - handleMissingRevisions(revisions, missingRevisions); - } - finally - { - releaseAtomicRequestLock(loadAndAddLock); - } + DetachedCDORevision detached = (DetachedCDORevision)revision; + return new RevisionInfo.Available.Detached(detached.getID(), requestedBranchPoint, detached); } - return revisions; + return new RevisionInfo.Available.Normal(revision.getID(), requestedBranchPoint, revision); + } + + private RevisionInfo.Missing createRevisionInfoMissing(CDOID id, CDOBranchPoint requestedBranchPoint) + { + return new RevisionInfo.Missing(id, requestedBranchPoint); } - public List<CDORevision> getRevisionsByTime(Collection<CDOID> ids, int referenceChunk, int prefetchDepth, - long timeStamp, boolean loadOnDemand) + private void loadRevisions(List<RevisionInfo> infosToLoad, CDOBranchPoint branchPoint, int referenceChunk, + int prefetchDepth) { - List<CDOID> missingIDs = loadOnDemand ? new ArrayList<CDOID>(0) : null; - List<CDORevision> revisions = new ArrayList<CDORevision>(ids.size()); - for (CDOID id : ids) + if (loadCounterForTest != null) { - InternalCDORevision revision = getRevisionByTime(id, referenceChunk, prefetchDepth, timeStamp, false); - revisions.add(revision); - if (revision == null && missingIDs != null) + for (int i = 0; i < infosToLoad.size(); i++) { - missingIDs.add(id); + loadCounterForTest.incrementAndGet(); } } - if (missingIDs != null && !missingIDs.isEmpty()) + acquireAtomicRequestLock(loadAndAddLock); + + try { - acquireAtomicRequestLock(loadAndAddLock); + List<InternalCDORevision> additionalRevisions = // + revisionLoader.loadRevisions(infosToLoad, branchPoint, referenceChunk, prefetchDepth); - try - { - List<InternalCDORevision> missingRevisions = revisionLoader.loadRevisionsByTime(missingIDs, referenceChunk, - prefetchDepth, timeStamp); - handleMissingRevisions(revisions, missingRevisions); - } - finally + if (additionalRevisions != null) { - releaseAtomicRequestLock(loadAndAddLock); + for (InternalCDORevision revision : additionalRevisions) + { + addRevision(revision); + } } } - - return revisions; + finally + { + releaseAtomicRequestLock(loadAndAddLock); + } } - private void addCachedRevisionIfNotNull(InternalCDORevision revision) + private List<CDORevision> getResultsAndSynthetics(RevisionInfo[] infos, SyntheticCDORevision[] synthetics) { - if (revision != null) + List<CDORevision> results = new ArrayList<CDORevision>(infos.length); + for (int i = 0; i < infos.length; i++) { - cache.addRevision(revision); + RevisionInfo info = infos[i]; + info.processResult(this, results, synthetics, i); } + + return results; } - protected InternalCDORevision verifyRevision(InternalCDORevision revision, int referenceChunk) + public boolean addRevision(CDORevision revision) { - return revision; + if (revision != null) + { + if (revision instanceof PointerCDORevision) + { + PointerCDORevision pointer = (PointerCDORevision)revision; + CDOBranchVersion target = pointer.getTarget(); + if (target instanceof InternalCDORevision) + { + revision = new PointerCDORevision(pointer.getID(), pointer.getBranch(), pointer.getRevised(), // + CDOBranchUtil.createBranchVersion(target)); + } + } + + boolean added = cache.addRevision(revision); + if (added) + { + int oldVersion = revision.getVersion() - 1; + if (oldVersion >= CDORevision.UNSPECIFIED_VERSION) + { + CDOBranchVersion old = CDOBranchUtil.createBranchVersion(revision.getBranch(), oldVersion); + InternalCDORevision oldRevision = getCachedRevisionByVersion(revision.getID(), old); + if (oldRevision != null) + { + oldRevision.setRevised(revision.getTimeStamp() - 1); + } + + return true; + } + } + } + + return false; } @Override @@ -380,7 +422,12 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi if (cache == null) { - cache = CDORevisionCacheUtil.createDefaultCache(); + cache = (InternalCDORevisionCache)CDORevisionCacheUtil.createDefaultCache(supportingBranches); + } + + if (supportingBranches && !cache.isSupportingBranches()) + { + throw new IllegalStateException("Revision cache does not support branches"); } } @@ -414,18 +461,33 @@ public class CDORevisionManagerImpl extends Lifecycle implements InternalCDORevi } } - private void handleMissingRevisions(List<CDORevision> revisions, List<InternalCDORevision> missingRevisions) + private InternalCDORevision getCachedRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) + { + return (InternalCDORevision)cache.getRevisionByVersion(id, branchVersion); + } + + private InternalCDORevision getCachedRevision(CDOID id, CDOBranchPoint branchPoint) + { + return (InternalCDORevision)cache.getRevision(id, branchPoint); + } + + private InternalCDORevision getCachedRevisionRecursively(CDOID id, CDOBranchPoint branchPoint) { - Iterator<InternalCDORevision> it = missingRevisions.iterator(); - for (int i = 0; i < revisions.size(); i++) + CDOBranch branch = branchPoint.getBranch(); + if (!branch.isMainBranch()) { - CDORevision revision = revisions.get(i); - if (revision == null) + CDOBranchPoint base = branch.getBase(); + InternalCDORevision revision = getCachedRevision(id, base); + if (revision != null) { - InternalCDORevision missingRevision = it.next(); - revisions.set(i, missingRevision); - addCachedRevisionIfNotNull(missingRevision); + return revision; } + + // Recurse + return getCachedRevisionRecursively(id, base); } + + // Reached main branch + return null; } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/EvictionEventImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/EvictionEventImpl.java index 3a0486fe86..1215c6bc89 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/EvictionEventImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/EvictionEventImpl.java @@ -10,7 +10,9 @@ */ package org.eclipse.emf.cdo.internal.common.revision.cache; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevisionKey; import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache.EvictionEvent; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; @@ -24,25 +26,12 @@ public class EvictionEventImpl extends Event implements EvictionEvent { private static final long serialVersionUID = 1L; - private CDOID id; + private CDORevisionKey key; - private int version; - - private InternalCDORevision revision; - - public EvictionEventImpl(CDORevisionCache cache, InternalCDORevision revision) - { - super(cache); - id = revision.getID(); - version = revision.getVersion(); - this.revision = revision; - } - - public EvictionEventImpl(CDORevisionCache cache, CDOID id, int version) + public EvictionEventImpl(CDORevisionCache cache, CDORevisionKey key) { super(cache); - this.id = id; - this.version = version; + this.key = key; } @Override @@ -53,16 +42,26 @@ public class EvictionEventImpl extends Event implements EvictionEvent public CDOID getID() { - return id; + return key.getID(); + } + + public CDOBranch getBranch() + { + return key.getBranch(); } public int getVersion() { - return version; + return key.getVersion(); } public InternalCDORevision getRevision() { - return revision; + if (key instanceof InternalCDORevision) + { + return (InternalCDORevision)key; + } + + return null; } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/branch/BranchDispatcher.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/branch/BranchDispatcher.java new file mode 100644 index 0000000000..ac42dedbb7 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/branch/BranchDispatcher.java @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2004 - 2009 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.internal.common.revision.cache.branch; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCacheFactory; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; + +import org.eclipse.net4j.util.lifecycle.Lifecycle; +import org.eclipse.net4j.util.lifecycle.LifecycleUtil; + +import org.eclipse.emf.ecore.EClass; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public class BranchDispatcher extends Lifecycle implements InternalCDORevisionCache +{ + private Map<CDOBranch, InternalCDORevisionCache> caches = new HashMap<CDOBranch, InternalCDORevisionCache>(); + + private CDORevisionCacheFactory factory; + + public BranchDispatcher() + { + } + + public InternalCDORevisionCache instantiate(CDORevision revision) + { + BranchDispatcher cache = new BranchDispatcher(); + cache.setFactory(factory); + return cache; + } + + public boolean isSupportingBranches() + { + return true; + } + + public CDORevisionCacheFactory getFactory() + { + return factory; + } + + public void setFactory(CDORevisionCacheFactory factory) + { + checkInactive(); + this.factory = factory; + } + + public EClass getObjectType(CDOID id) + { + for (CDORevisionCache cache : getCaches()) + { + EClass type = cache.getObjectType(id); + if (type != null) + { + return type; + } + } + + return null; + } + + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint) + { + CDORevisionCache cache = getCache(branchPoint.getBranch()); + if (cache == null) + { + return null; + } + + return cache.getRevision(id, branchPoint); + } + + public CDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) + { + CDORevisionCache cache = getCache(branchVersion.getBranch()); + if (cache == null) + { + return null; + } + + return cache.getRevisionByVersion(id, branchVersion); + } + + public CDORevision removeRevision(CDOID id, CDOBranchVersion branchVersion) + { + InternalCDORevisionCache cache = getCache(branchVersion.getBranch()); + if (cache == null) + { + return null; + } + + return cache.removeRevision(id, branchVersion); + } + + public boolean addRevision(CDORevision revision) + { + InternalCDORevisionCache cache; + CDOBranch branch = revision.getBranch(); + synchronized (caches) + { + cache = caches.get(branch); + if (cache == null) + { + cache = (InternalCDORevisionCache)factory.createRevisionCache(revision); + LifecycleUtil.activate(cache); + caches.put(branch, cache); + } + } + + return cache.addRevision(revision); + } + + public List<CDORevision> getCurrentRevisions() + { + List<CDORevision> result = new ArrayList<CDORevision>(); + for (CDORevisionCache cache : getCaches()) + { + result.addAll(cache.getCurrentRevisions()); + } + + return result; + } + + public void clear() + { + for (InternalCDORevisionCache cache : getCaches()) + { + cache.clear(); + } + } + + public Map<CDOBranch, List<CDORevision>> getAllRevisions() + { + throw new UnsupportedOperationException(); + } + + @Override + protected void doBeforeActivate() throws Exception + { + super.doBeforeActivate(); + checkState(factory, "factory"); + } + + @Override + protected void doDeactivate() throws Exception + { + for (CDORevisionCache cache : getCaches()) + { + LifecycleUtil.deactivate(cache); + } + + super.doDeactivate(); + } + + private InternalCDORevisionCache getCache(CDOBranch branch) + { + synchronized (caches) + { + return caches.get(branch); + } + } + + private InternalCDORevisionCache[] getCaches() + { + synchronized (caches) + { + return caches.values().toArray(new InternalCDORevisionCache[caches.size()]); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/branch/BranchRevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/branch/BranchRevisionCache.java new file mode 100644 index 0000000000..06c02d0c1a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/branch/BranchRevisionCache.java @@ -0,0 +1,500 @@ +/** + * Copyright (c) 2004 - 2009 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 + * Simon McDuff - bug 201266 + * Simon McDuff - bug 230832 + */ +package org.eclipse.emf.cdo.internal.common.revision.cache.branch; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDAndBranch; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionKey; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; +import org.eclipse.emf.cdo.internal.common.bundle.OM; +import org.eclipse.emf.cdo.internal.common.revision.cache.EvictionEventImpl; +import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; + +import org.eclipse.net4j.util.CheckUtil; +import org.eclipse.net4j.util.event.IListener; +import org.eclipse.net4j.util.om.trace.ContextTracer; +import org.eclipse.net4j.util.ref.KeyedReference; +import org.eclipse.net4j.util.ref.KeyedSoftReference; +import org.eclipse.net4j.util.ref.KeyedStrongReference; +import org.eclipse.net4j.util.ref.ReferenceQueueWorker; + +import org.eclipse.emf.ecore.EClass; + +import java.lang.ref.Reference; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Map.Entry; + +/** + * @author Eike Stepper + */ +public class BranchRevisionCache extends ReferenceQueueWorker<InternalCDORevision> implements InternalCDORevisionCache +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, BranchRevisionCache.class); + + private static boolean disableGC = false; + + private Map<CDOIDAndBranch, RevisionList> revisionLists = new HashMap<CDOIDAndBranch, RevisionList>(); + + public BranchRevisionCache() + { + } + + public InternalCDORevisionCache instantiate(CDORevision revision) + { + return new BranchRevisionCache(); + } + + public boolean isSupportingBranches() + { + return true; + } + + public EClass getObjectType(CDOID id) + { + synchronized (revisionLists) + { + for (Entry<CDOIDAndBranch, RevisionList> entry : revisionLists.entrySet()) + { + if (id.equals(entry.getKey().getID())) + { + RevisionList revisionList = entry.getValue(); + EClass type = revisionList.getObjectType(); + if (type != null) + { + return type; + } + } + } + } + + return null; + } + + public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint) + { + RevisionList revisionList = getRevisionList(id, branchPoint.getBranch()); + if (revisionList != null) + { + return revisionList.getRevision(branchPoint.getTimeStamp()); + } + + return null; + } + + public InternalCDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) + { + RevisionList revisionList = getRevisionList(id, branchVersion.getBranch()); + if (revisionList != null) + { + return revisionList.getRevisionByVersion(branchVersion.getVersion()); + } + + return null; + } + + public List<CDORevision> getCurrentRevisions() + { + List<CDORevision> currentRevisions = new ArrayList<CDORevision>(); + synchronized (revisionLists) + { + for (RevisionList revisionList : revisionLists.values()) + { + InternalCDORevision revision = revisionList.getRevision(CDORevision.UNSPECIFIED_DATE); + if (revision != null) + { + currentRevisions.add(revision); + } + } + } + + return currentRevisions; + } + + public boolean addRevision(CDORevision revision) + { + CheckUtil.checkArg(revision, "revision"); + CDOIDAndBranch key = CDOIDUtil.createIDAndBranch(revision.getID(), revision.getBranch()); + synchronized (revisionLists) + { + RevisionList list = revisionLists.get(key); + if (list == null) + { + list = new RevisionList(); + revisionLists.put(key, list); + } + + InternalCDORevision rev = (InternalCDORevision)revision; + return list.addRevision(rev, createReference(key, rev)); + } + } + + public InternalCDORevision removeRevision(CDOID id, CDOBranchVersion branchVersion) + { + CDOIDAndBranch key = CDOIDUtil.createIDAndBranch(id, branchVersion.getBranch()); + synchronized (revisionLists) + { + RevisionList list = revisionLists.get(key); + if (list != null) + { + list.removeRevision(branchVersion.getVersion()); + if (list.isEmpty()) + { + revisionLists.remove(key); + if (TRACER.isEnabled()) + { + TRACER.format("Removed cache list of {0}", key); //$NON-NLS-1$ + } + } + } + } + + return null; + } + + public void clear() + { + synchronized (revisionLists) + { + revisionLists.clear(); + } + } + + @Override + public String toString() + { + return revisionLists.toString(); + } + + public Map<CDOBranch, List<CDORevision>> getAllRevisions() + { + Map<CDOBranch, List<CDORevision>> result = new HashMap<CDOBranch, List<CDORevision>>(); + for (RevisionList list : revisionLists.values()) + { + list.getAllRevisions(result); + } + + return result; + } + + @Override + protected void work(Reference<? extends InternalCDORevision> reference) + { + @SuppressWarnings("unchecked") + KeyedReference<CDORevisionKey, InternalCDORevision> keyedRef = (KeyedReference<CDORevisionKey, InternalCDORevision>)reference; + CDORevisionKey key = keyedRef.getKey(); + + CDOID id = key.getID(); + CDOBranch branch = key.getBranch(); + int version = key.getVersion(); + + InternalCDORevision revision = removeRevision(id, CDOBranchUtil.createBranchVersion(branch, version)); + if (revision == null) + { + // Use revision in eviction event + key = revision; + } + + IListener[] listeners = getListeners(); + if (listeners != null) + { + fireEvent(new EvictionEventImpl(this, key), listeners); + } + } + + private KeyedReference<CDORevisionKey, InternalCDORevision> createReference(CDOIDAndBranch idAndBranch, + InternalCDORevision revision) + { + CDORevisionKey key = new RevisionKey(idAndBranch, revision.getVersion()); + if (disableGC) + { + return new KeyedStrongReference<CDORevisionKey, InternalCDORevision>(key, revision); + } + + return new KeyedSoftReference<CDORevisionKey, InternalCDORevision>(key, revision, getQueue()); + } + + private RevisionList getRevisionList(CDOID id, CDOBranch branch) + { + CDOIDAndBranch key = CDOIDUtil.createIDAndBranch(id, branch); + synchronized (revisionLists) + { + return revisionLists.get(key); + } + } + + /** + * @author Eike Stepper + */ + private static final class RevisionKey implements CDORevisionKey + { + private CDOIDAndBranch idAndBranch; + + private int version; + + public RevisionKey(CDOIDAndBranch idAndBranch, int version) + { + this.idAndBranch = idAndBranch; + this.version = version; + } + + public CDOID getID() + { + return idAndBranch.getID(); + } + + public CDOBranch getBranch() + { + return idAndBranch.getBranch(); + } + + public int getVersion() + { + return version; + } + + @Override + public String toString() + { + return MessageFormat.format("{0}:{1}v{2}", getID(), getBranch().getID(), getVersion()); + } + } + + /** + * @author Eike Stepper + */ + private static final class RevisionList extends LinkedList<KeyedReference<CDORevisionKey, InternalCDORevision>> + { + private static final long serialVersionUID = 1L; + + public RevisionList() + { + } + + public synchronized EClass getObjectType() + { + for (Iterator<KeyedReference<CDORevisionKey, InternalCDORevision>> it = iterator(); it.hasNext();) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = it.next(); + InternalCDORevision revision = ref.get(); + if (revision != null) + { + EClass type = revision.getEClass(); + if (type != null) + { + return type; + } + } + + it.remove(); + } + + return null; + } + + public synchronized InternalCDORevision getRevision(long timeStamp) + { + if (timeStamp == CDORevision.UNSPECIFIED_DATE) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = isEmpty() ? null : getFirst(); + if (ref != null) + { + InternalCDORevision revision = ref.get(); + if (revision != null) + { + if (!revision.isHistorical()) + { + return revision; + } + } + else + { + removeFirst(); + } + } + + return null; + } + + for (Iterator<KeyedReference<CDORevisionKey, InternalCDORevision>> it = iterator(); it.hasNext();) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = it.next(); + InternalCDORevision revision = ref.get(); + if (revision != null) + { + long created = revision.getTimeStamp(); + if (created <= timeStamp) + { + long revised = revision.getRevised(); + if (timeStamp <= revised || revised == CDORevision.UNSPECIFIED_DATE) + { + return revision; + } + else + { + break; + } + } + } + else + { + it.remove(); + } + } + + return null; + } + + public synchronized InternalCDORevision getRevisionByVersion(int version) + { + for (Iterator<KeyedReference<CDORevisionKey, InternalCDORevision>> it = iterator(); it.hasNext();) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = it.next(); + InternalCDORevision revision = ref.get(); + if (revision != null) + { + int v = revision.getVersion(); + if (v == version) + { + return revision; + } + else if (v < version) + { + break; + } + } + else + { + it.remove(); + } + } + + return null; + } + + public synchronized boolean addRevision(InternalCDORevision revision, + KeyedReference<CDORevisionKey, InternalCDORevision> reference) + { + int version = revision.getVersion(); + for (ListIterator<KeyedReference<CDORevisionKey, InternalCDORevision>> it = listIterator(); it.hasNext();) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = it.next(); + InternalCDORevision foundRevision = ref.get(); + if (foundRevision != null) + { + CDORevisionKey key = ref.getKey(); + int v = key.getVersion(); + if (v == version) + { + return false; + } + + if (v < version) + { + it.previous(); + it.add(reference); + return true; + } + } + else + { + it.remove(); + } + } + + addLast(reference); + return true; + } + + public synchronized void removeRevision(int version) + { + for (Iterator<KeyedReference<CDORevisionKey, InternalCDORevision>> it = iterator(); it.hasNext();) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = it.next(); + CDORevisionKey key = ref.getKey(); + int v = key.getVersion(); + if (v == version) + { + it.remove(); + if (TRACER.isEnabled()) + { + TRACER.format("Removed version {0} from cache list of {1}", version, key.getID()); //$NON-NLS-1$ + } + + break; + } + else if (v < version) + { + break; + } + } + } + + @Override + public String toString() + { + StringBuffer buffer = new StringBuffer(); + for (Iterator<KeyedReference<CDORevisionKey, InternalCDORevision>> it = iterator(); it.hasNext();) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = it.next(); + InternalCDORevision revision = ref.get(); + if (buffer.length() == 0) + { + buffer.append("{"); + } + else + { + buffer.append(", "); + } + + buffer.append(revision); + } + + buffer.append("}"); + return buffer.toString(); + } + + public void getAllRevisions(Map<CDOBranch, List<CDORevision>> result) + { + for (Iterator<KeyedReference<CDORevisionKey, InternalCDORevision>> it = iterator(); it.hasNext();) + { + KeyedReference<CDORevisionKey, InternalCDORevision> ref = it.next(); + InternalCDORevision revision = ref.get(); + if (revision != null) + { + CDOBranch branch = revision.getBranch(); + List<CDORevision> resultList = result.get(branch); + if (resultList == null) + { + resultList = new ArrayList<CDORevision>(1); + result.put(branch, resultList); + } + + resultList.add(revision); + } + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/LRURevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/LRURevisionCache.java index 8b219a1ecb..17567247f2 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/LRURevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/LRURevisionCache.java @@ -11,9 +11,12 @@ */ package org.eclipse.emf.cdo.internal.common.revision.cache.lru; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; import org.eclipse.emf.cdo.internal.common.bundle.OM; import org.eclipse.emf.cdo.internal.common.revision.cache.EvictionEventImpl; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; @@ -34,7 +37,7 @@ import java.util.Map; /** * @author Eike Stepper */ -public class LRURevisionCache extends Lifecycle implements CDORevisionCache +public class LRURevisionCache extends Lifecycle implements InternalCDORevisionCache { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, LRURevisionCache.class); @@ -52,6 +55,19 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache { } + public InternalCDORevisionCache instantiate(CDORevision revision) + { + LRURevisionCache cache = new LRURevisionCache(); + cache.setCapacityCurrent(capacityCurrent); + cache.setCapacityRevised(capacityRevised); + return cache; + } + + public boolean isSupportingBranches() + { + return false; + } + public int getCapacityCurrent() { return capacityCurrent; @@ -88,13 +104,13 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache } } - public synchronized List<CDORevision> getRevisions() + public synchronized List<CDORevision> getCurrentRevisions() { List<CDORevision> currentRevisions = new ArrayList<CDORevision>(); for (RevisionHolder holder : revisions.values()) { InternalCDORevision revision = holder.getRevision(); - if (revision != null && revision.isCurrent()) + if (revision != null && !revision.isHistorical()) { currentRevisions.add(revision); } @@ -115,30 +131,19 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache return revision.getEClass(); } - public synchronized InternalCDORevision getRevision(CDOID id) + public synchronized InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint) { RevisionHolder holder = getHolder(id); - InternalCDORevision revision = holder == null ? null : holder.getRevision(); - if (revision == null || !revision.isCurrent()) - { - return null; - } - - return revision; + return getRevision(holder, branchPoint.getTimeStamp()); } - public synchronized InternalCDORevision getRevisionByTime(CDOID id, long timeStamp) - { - RevisionHolder holder = getHolder(id); - return getRevisionByTime(holder, timeStamp); - } - - public synchronized InternalCDORevision getRevisionByVersion(CDOID id, int version) + public synchronized InternalCDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) { RevisionHolder holder = getHolder(id); while (holder != null) { int holderVersion = holder.getVersion(); + int version = branchVersion.getVersion(); if (holderVersion > version) { holder = holder.getNext(); @@ -161,8 +166,10 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache CheckUtil.checkArg(revision, "revision"); if (TRACER.isEnabled()) { - TRACER.format("Adding revision: {0}, created={1,date} {1,time}, revised={2,date} {2,time}, current={3}", //$NON-NLS-1$ - revision, revision.getCreated(), revision.getRevised(), revision.isCurrent()); + TRACER + .format( + "Adding revision: {0}, timeStamp={1,date} {1,time,HH:mm:ss:SSS}, revised={2,date} {2,time,HH:mm:ss:SSS}, historical={3}", //$NON-NLS-1$ + revision, revision.getTimeStamp(), revision.getRevised(), revision.isHistorical()); } int version = revision.getVersion(); @@ -188,25 +195,21 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache // Create holder only if require RevisionHolder newHolder = createHolder((InternalCDORevision)revision); - LRU list = revision.isCurrent() ? currentLRU : revisedLRU; + LRU list = revision.isHistorical() ? revisedLRU : currentLRU; list.add((DLRevisionHolder)newHolder); adjustHolder((InternalCDORevision)revision, newHolder, lastHolder, holder); return true; } - public synchronized void removeRevision(CDORevision revision) - { - removeRevision(revision.getID(), revision.getVersion()); - } - - public synchronized InternalCDORevision removeRevision(CDOID id, int version) + public synchronized InternalCDORevision removeRevision(CDOID id, CDOBranchVersion branchVersion) { InternalCDORevision revision = null; RevisionHolder holder = getHolder(id); while (holder != null) { int holderVersion = holder.getVersion(); + int version = branchVersion.getVersion(); if (holderVersion > version) { holder = holder.getNext(); @@ -216,7 +219,7 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache if (holderVersion == version) { revision = holder.getRevision(); - LRU list = revision.isCurrent() ? currentLRU : revisedLRU; + LRU list = revision.isHistorical() ? revisedLRU : currentLRU; list.remove((DLRevisionHolder)holder); removeHolder(holder); } @@ -228,7 +231,7 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache return revision; } - public synchronized boolean removeRevisions(CDOID id) + public synchronized boolean removeRevisions(CDOID id, CDOBranch branch) { RevisionHolder lookupHolder = getHolder(id); RevisionHolder holder = lookupHolder; @@ -249,7 +252,12 @@ public class LRURevisionCache extends Lifecycle implements CDORevisionCache revisedLRU = new LRU(capacityRevised); } - private InternalCDORevision getRevisionByTime(RevisionHolder holder, long timeStamp) + public Map<CDOBranch, List<CDORevision>> getAllRevisions() + { + throw new UnsupportedOperationException(); + } + + private InternalCDORevision getRevision(RevisionHolder holder, long timeStamp) { while (holder != null) { diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/RevisionHolder.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/RevisionHolder.java index 2b82146b30..afb658cb57 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/RevisionHolder.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/lru/RevisionHolder.java @@ -4,7 +4,7 @@ * 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 */ @@ -44,7 +44,7 @@ public class RevisionHolder public long getCreated() { - return revision.getCreated(); + return revision.getTimeStamp(); } public long getRevised() diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/mem/MEMRevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/mem/MEMRevisionCache.java index 7fc2afcc38..5496c419b7 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/mem/MEMRevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/mem/MEMRevisionCache.java @@ -12,14 +12,19 @@ */ package org.eclipse.emf.cdo.internal.common.revision.cache.mem; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDAndVersion; import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; import org.eclipse.emf.cdo.internal.common.bundle.OM; import org.eclipse.emf.cdo.internal.common.messages.Messages; import org.eclipse.emf.cdo.internal.common.revision.cache.EvictionEventImpl; +import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.net4j.util.CheckUtil; @@ -49,7 +54,7 @@ import java.util.Map.Entry; /** * @author Eike Stepper */ -public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> implements CDORevisionCache +public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> implements InternalCDORevisionCache { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, MEMRevisionCache.class); @@ -59,7 +64,7 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> public MEMRevisionCache(ReferenceType referenceType) { - this.referenceType = referenceType; + setReferenceType(referenceType); } public MEMRevisionCache() @@ -67,6 +72,16 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> this(ReferenceType.SOFT); } + public InternalCDORevisionCache instantiate(CDORevision revision) + { + return new MEMRevisionCache(referenceType); + } + + public boolean isSupportingBranches() + { + return false; + } + public ReferenceType getReferenceType() { return referenceType; @@ -74,6 +89,7 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> public void setReferenceType(ReferenceType referenceType) { + checkInactive(); this.referenceType = referenceType; } @@ -82,41 +98,28 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> return null; } - public InternalCDORevision getRevision(CDOID id) - { - synchronized (cacheLists) - { - CacheList list = cacheLists.get(id); - if (list != null) - { - return list.getRevision(); - } - } - - return null; - } - - public InternalCDORevision getRevisionByTime(CDOID id, long timeStamp) + public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint) { synchronized (cacheLists) { CacheList list = cacheLists.get(id); if (list != null) { - return list.getRevisionByTime(timeStamp); + return list.getRevision(branchPoint.getTimeStamp()); } } return null; } - public InternalCDORevision getRevisionByVersion(CDOID id, int version) + public InternalCDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) { synchronized (cacheLists) { CacheList list = cacheLists.get(id); if (list != null) { + int version = branchVersion.getVersion(); return list.getRevisionByVersion(version); } } @@ -124,7 +127,7 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> return null; } - public List<CDORevision> getRevisions() + public List<CDORevision> getCurrentRevisions() { ArrayList<CDORevision> currentRevisions = new ArrayList<CDORevision>(); synchronized (cacheLists) @@ -132,7 +135,7 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> for (Entry<CDOID, CacheList> entry : cacheLists.entrySet()) { CacheList list = entry.getValue(); - InternalCDORevision revision = list.getRevision(); + InternalCDORevision revision = list.getRevision(CDORevision.UNSPECIFIED_DATE); if (revision != null) { currentRevisions.add(revision); @@ -160,18 +163,14 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> } } - public void removeRevision(CDORevision revision) - { - removeRevision(revision.getID(), revision.getVersion()); - } - - public InternalCDORevision removeRevision(CDOID id, int version) + public InternalCDORevision removeRevision(CDOID id, CDOBranchVersion branchVersion) { synchronized (cacheLists) { CacheList list = cacheLists.get(id); if (list != null) { + int version = branchVersion.getVersion(); list.removeRevision(version); if (list.isEmpty()) { @@ -195,22 +194,28 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> } } + public Map<CDOBranch, List<CDORevision>> getAllRevisions() + { + throw new UnsupportedOperationException(); + } + @Override @SuppressWarnings("unchecked") protected void work(Reference<? extends InternalCDORevision> reference) { KeyedReference<CDOIDAndVersion, InternalCDORevision> keyedRef = (KeyedReference<CDOIDAndVersion, InternalCDORevision>)reference; CDOIDAndVersion key = keyedRef.getKey(); - CDOID id = key.getID(); - int version = key.getVersion(); + final CDOID id = key.getID(); + final CDOBranch branch = null; + final int version = key.getVersion(); - InternalCDORevision revision = removeRevision(id, version); + InternalCDORevision revision = removeRevision(id, CDOBranchUtil.createBranchVersion(branch, version)); if (revision == null) { IListener[] listeners = getListeners(); if (listeners != null) { - fireEvent(new EvictionEventImpl(this, id, version), listeners); + fireEvent(new EvictionEventImpl(this, CDORevisionUtil.createRevisionKey(id, branch, version)), listeners); } } else @@ -259,22 +264,53 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> { } - public InternalCDORevision getRevision() + public InternalCDORevision getRevision(long timeStamp) { - KeyedReference<CDOIDAndVersion, InternalCDORevision> ref = isEmpty() ? null : getFirst(); - if (ref != null) + if (timeStamp == CDORevision.UNSPECIFIED_DATE) + { + KeyedReference<CDOIDAndVersion, InternalCDORevision> ref = isEmpty() ? null : getFirst(); + if (ref != null) + { + InternalCDORevision revision = ref.get(); + if (revision != null) + { + if (!revision.isHistorical()) + { + return revision; + } + } + else + { + removeFirst(); + } + } + + return null; + } + + for (Iterator<KeyedReference<CDOIDAndVersion, InternalCDORevision>> it = iterator(); it.hasNext();) { + KeyedReference<CDOIDAndVersion, InternalCDORevision> ref = it.next(); InternalCDORevision revision = ref.get(); if (revision != null) { - if (revision.isCurrent()) + long created = revision.getTimeStamp(); + if (created <= timeStamp) { - return revision; + long revised = revision.getRevised(); + if (timeStamp <= revised || revised == CDORevision.UNSPECIFIED_DATE) + { + return revision; + } + else + { + break; + } } } else { - removeFirst(); + it.remove(); } } @@ -308,11 +344,6 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> return null; } - public InternalCDORevision getRevisionByTime(long timeStamp) - { - return getRevisionByTime(timeStamp, false); - } - public void removeRevision(int version) { for (Iterator<KeyedReference<CDOIDAndVersion, InternalCDORevision>> it = iterator(); it.hasNext();) @@ -344,7 +375,8 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> for (ListIterator<KeyedReference<CDOIDAndVersion, InternalCDORevision>> it = listIterator(); it.hasNext();) { KeyedReference<CDOIDAndVersion, InternalCDORevision> ref = it.next(); - if (ref.get() != null) + InternalCDORevision foundRevision = ref.get(); + if (foundRevision != null) { CDOIDAndVersion key = ref.getKey(); int v = key.getVersion(); @@ -369,41 +401,5 @@ public class MEMRevisionCache extends ReferenceQueueWorker<InternalCDORevision> addLast(reference); return true; } - - private InternalCDORevision getRevisionByTime(long timeStamp, boolean onlyResource) - { - for (Iterator<KeyedReference<CDOIDAndVersion, InternalCDORevision>> it = iterator(); it.hasNext();) - { - KeyedReference<CDOIDAndVersion, InternalCDORevision> ref = it.next(); - InternalCDORevision revision = ref.get(); - if (revision != null) - { - if (onlyResource && !revision.isResource()) - { - return null; - } - - long created = revision.getCreated(); - if (created <= timeStamp) - { - long revised = revision.getRevised(); - if (timeStamp <= revised || revised == CDORevision.UNSPECIFIED_DATE) - { - return revision; - } - else - { - break; - } - } - } - else - { - it.remove(); - } - } - - return null; - } } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/noop/NOOPRevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/noop/NOOPRevisionCache.java index e2c38b0756..342b55253a 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/noop/NOOPRevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/noop/NOOPRevisionCache.java @@ -10,9 +10,12 @@ */ package org.eclipse.emf.cdo.internal.common.revision.cache.noop; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; -import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.net4j.util.CheckUtil; @@ -22,11 +25,12 @@ import org.eclipse.emf.ecore.EClass; import java.util.Collections; import java.util.List; +import java.util.Map; /** * @author Eike Stepper */ -public class NOOPRevisionCache extends Lifecycle implements CDORevisionCache +public class NOOPRevisionCache extends Lifecycle implements InternalCDORevisionCache { public static final NOOPRevisionCache INSTANCE = new NOOPRevisionCache(); @@ -36,12 +40,22 @@ public class NOOPRevisionCache extends Lifecycle implements CDORevisionCache { } + public InternalCDORevisionCache instantiate(CDORevision revision) + { + return this; + } + + public boolean isSupportingBranches() + { + return true; + } + public EClass getObjectType(CDOID id) { return null; } - public List<CDORevision> getRevisions() + public List<CDORevision> getCurrentRevisions() { return EMPTY; } @@ -51,12 +65,12 @@ public class NOOPRevisionCache extends Lifecycle implements CDORevisionCache return null; } - public InternalCDORevision getRevisionByTime(CDOID id, long timeStamp) + public InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint) { return null; } - public InternalCDORevision getRevisionByVersion(CDOID id, int version) + public InternalCDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) { return null; } @@ -67,11 +81,7 @@ public class NOOPRevisionCache extends Lifecycle implements CDORevisionCache return false; } - public void removeRevision(CDORevision revision) - { - } - - public InternalCDORevision removeRevision(CDOID id, int version) + public InternalCDORevision removeRevision(CDOID id, CDOBranchVersion branchVersion) { return null; } @@ -80,4 +90,9 @@ public class NOOPRevisionCache extends Lifecycle implements CDORevisionCache { // Do nothing } + + public Map<CDOBranch, List<CDORevision>> getAllRevisions() + { + return Collections.emptyMap(); + } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/two/TwoLevelRevisionCache.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/two/TwoLevelRevisionCache.java index aa39556701..d56c635e61 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/two/TwoLevelRevisionCache.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/cache/two/TwoLevelRevisionCache.java @@ -12,9 +12,13 @@ */ package org.eclipse.emf.cdo.internal.common.revision.cache.two; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; import org.eclipse.emf.cdo.internal.common.bundle.OM; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; @@ -29,38 +33,52 @@ import org.eclipse.emf.ecore.EClass; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * @author Eike Stepper */ -public class TwoLevelRevisionCache extends Lifecycle implements CDORevisionCache, IListener +public class TwoLevelRevisionCache extends Lifecycle implements InternalCDORevisionCache, IListener { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, TwoLevelRevisionCache.class); - private CDORevisionCache level1; + private InternalCDORevisionCache level1; - private CDORevisionCache level2; + private InternalCDORevisionCache level2; public TwoLevelRevisionCache() { } - public CDORevisionCache getLevel1() + public InternalCDORevisionCache instantiate(CDORevision revision) + { + TwoLevelRevisionCache cache = new TwoLevelRevisionCache(); + cache.setLevel1(level1.instantiate(revision)); + cache.setLevel2(level2.instantiate(revision)); + return cache; + } + + public boolean isSupportingBranches() + { + return false; + } + + public InternalCDORevisionCache getLevel1() { return level1; } - public void setLevel1(CDORevisionCache level1) + public void setLevel1(InternalCDORevisionCache level1) { this.level1 = level1; } - public CDORevisionCache getLevel2() + public InternalCDORevisionCache getLevel2() { return level2; } - public void setLevel2(CDORevisionCache level2) + public void setLevel2(InternalCDORevisionCache level2) { this.level2 = level2; } @@ -76,44 +94,33 @@ public class TwoLevelRevisionCache extends Lifecycle implements CDORevisionCache return objectType; } - public CDORevision getRevision(CDOID id) + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint) { - CDORevision revision = level1.getRevision(id); + CDORevision revision = level1.getRevision(id, branchPoint); if (revision == null) { - revision = level2.getRevision(id); + revision = level2.getRevision(id, branchPoint); } return revision; } - public CDORevision getRevisionByTime(CDOID id, long timeStamp) + public CDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) { - CDORevision revision = level1.getRevisionByTime(id, timeStamp); + CDORevision revision = level1.getRevisionByVersion(id, branchVersion); if (revision == null) { - revision = level2.getRevisionByTime(id, timeStamp); + revision = level2.getRevisionByVersion(id, branchVersion); } return revision; } - public CDORevision getRevisionByVersion(CDOID id, int version) - { - CDORevision revision = level1.getRevisionByVersion(id, version); - if (revision == null) - { - revision = level2.getRevisionByVersion(id, version); - } - - return revision; - } - - public List<CDORevision> getRevisions() + public List<CDORevision> getCurrentRevisions() { List<CDORevision> revisions = new ArrayList<CDORevision>(); - revisions.addAll(level1.getRevisions()); - revisions.addAll(level2.getRevisions()); + revisions.addAll(level1.getCurrentRevisions()); + revisions.addAll(level2.getCurrentRevisions()); return revisions; } @@ -124,20 +131,20 @@ public class TwoLevelRevisionCache extends Lifecycle implements CDORevisionCache // Bugzilla 292372: If a new current revision was added to level1, we must check whether // level2 contains a stale current revision, and revise that revision if possible - if (added && revision.isCurrent()) + if (added && !revision.isHistorical()) { CDOID id = revision.getID(); - CDORevision revisionInLevel2 = level2.getRevision(id); - if (revisionInLevel2 != null && revisionInLevel2.isCurrent()) + CDORevision revisionInLevel2 = level2.getRevision(id, revision); + if (revisionInLevel2 != null && !revisionInLevel2.isHistorical()) { // We can only revise if the revisions are consecutive if (revision.getVersion() == revisionInLevel2.getVersion() + 1) { - ((InternalCDORevision)revisionInLevel2).setRevised(revision.getCreated() - 1); + ((InternalCDORevision)revisionInLevel2).setRevised(revision.getTimeStamp() - 1); } else { - level2.removeRevision(id, revisionInLevel2.getVersion()); + level2.removeRevision(id, revision.getBranch().getVersion(revisionInLevel2.getVersion())); } } } @@ -145,20 +152,11 @@ public class TwoLevelRevisionCache extends Lifecycle implements CDORevisionCache return added; } - public void removeRevision(CDORevision revision) - { - removeRevision(revision.getID(), revision.getVersion()); - } - - public CDORevision removeRevision(CDOID id, int version) + public CDORevision removeRevision(CDOID id, CDOBranchVersion branchVersion) { - CDORevision revision = level1.removeRevision(id, version); - if (revision == null) - { - revision = level2.removeRevision(id, version); - } - - return revision; + CDORevision revision1 = level1.removeRevision(id, branchVersion); + CDORevision revision2 = level2.removeRevision(id, branchVersion); + return revision1 != null ? revision1 : revision2; } public void clear() @@ -167,6 +165,11 @@ public class TwoLevelRevisionCache extends Lifecycle implements CDORevisionCache level2.clear(); } + public Map<CDOBranch, List<CDORevision>> getAllRevisions() + { + throw new UnsupportedOperationException(); + } + public void notifyEvent(IEvent event) { if (event instanceof EvictionEvent) diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java index 1fedcee224..7e7a9401f7 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDORevisionDeltaImpl.java @@ -12,6 +12,7 @@ */ package org.eclipse.emf.cdo.internal.common.revision.delta; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.io.CDODataInput; import org.eclipse.emf.cdo.common.io.CDODataOutput; @@ -24,7 +25,6 @@ import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor; import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; -import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; import org.eclipse.emf.ecore.EClass; @@ -42,30 +42,30 @@ import java.util.Map; */ public class CDORevisionDeltaImpl implements InternalCDORevisionDelta { - private CDOID cdoID; - private EClass eClass; - private int dirtyVersion; + private CDOID id; + + private CDOBranch branch; - private int originVersion; + private int version; private Map<EStructuralFeature, CDOFeatureDelta> featureDeltas = new HashMap<EStructuralFeature, CDOFeatureDelta>(); public CDORevisionDeltaImpl(CDORevision revision) { - cdoID = revision.getID(); eClass = revision.getEClass(); - dirtyVersion = revision.getVersion(); - originVersion = dirtyVersion - 1; + id = revision.getID(); + branch = revision.getBranch(); + version = revision.getVersion(); } public CDORevisionDeltaImpl(CDORevisionDelta revisionDelta) { - cdoID = revisionDelta.getID(); - eClass = ((CDORevisionDeltaImpl)revisionDelta).eClass; - dirtyVersion = revisionDelta.getDirtyVersion(); - originVersion = revisionDelta.getOriginVersion(); + eClass = revisionDelta.getEClass(); + id = revisionDelta.getID(); + branch = revisionDelta.getBranch(); + version = revisionDelta.getVersion(); for (CDOFeatureDelta delta : revisionDelta.getFeatureDeltas()) { @@ -75,15 +75,18 @@ public class CDORevisionDeltaImpl implements InternalCDORevisionDelta public CDORevisionDeltaImpl(CDORevision originRevision, CDORevision dirtyRevision) { - if (originRevision.getEClass() != dirtyRevision.getEClass()) + if ( // + originRevision.getEClass() // + != // + dirtyRevision.getEClass()) { throw new IllegalArgumentException(); } - cdoID = originRevision.getID(); eClass = originRevision.getEClass(); - dirtyVersion = dirtyRevision.getVersion(); - originVersion = originRevision.getVersion(); + id = originRevision.getID(); + branch = originRevision.getBranch(); + version = originRevision.getVersion(); compare(originRevision, dirtyRevision); @@ -101,9 +104,9 @@ public class CDORevisionDeltaImpl implements InternalCDORevisionDelta public CDORevisionDeltaImpl(CDODataInput in) throws IOException { eClass = (EClass)in.readCDOClassifierRefAndResolve(); - cdoID = in.readCDOID(); - originVersion = in.readInt(); - dirtyVersion = in.readInt(); + id = in.readCDOID(); + branch = in.readCDOBranch(); + version = in.readInt(); int size = in.readInt(); for (int i = 0; i < size; i++) { @@ -115,9 +118,9 @@ public class CDORevisionDeltaImpl implements InternalCDORevisionDelta public void write(CDODataOutput out) throws IOException { out.writeCDOClassifierRef(eClass); - out.writeCDOID(cdoID); - out.writeInt(originVersion); - out.writeInt(dirtyVersion); + out.writeCDOID(id); + out.writeCDOBranch(branch); + out.writeInt(version); out.writeInt(featureDeltas.size()); for (CDOFeatureDelta featureDelta : featureDeltas.values()) { @@ -125,34 +128,34 @@ public class CDORevisionDeltaImpl implements InternalCDORevisionDelta } } - public CDOID getID() + public EClass getEClass() { - return cdoID; + return eClass; } - public EClass getEClass() + public CDOID getID() { - return eClass; + return id; } - public int getOriginVersion() + public CDOBranch getBranch() { - return originVersion; + return branch; } - public void setOriginVersion(int originVersion) + public void setBranch(CDOBranch branch) { - this.originVersion = originVersion; + this.branch = branch; } - public int getDirtyVersion() + public int getVersion() { - return dirtyVersion; + return version; } - public void setDirtyVersion(int dirtyVersion) + public void setVersion(int version) { - this.dirtyVersion = dirtyVersion; + this.version = version; } public List<CDOFeatureDelta> getFeatureDeltas() @@ -162,7 +165,8 @@ public class CDORevisionDeltaImpl implements InternalCDORevisionDelta public void apply(CDORevision revision) { - ((InternalCDORevision)revision).setVersion(dirtyVersion); + // ((InternalCDORevision)revision).setBranchPoint(branch.getPoint(revision.getTimeStamp())); + // ((InternalCDORevision)revision).setVersion(version); for (CDOFeatureDelta featureDelta : featureDeltas.values()) { ((CDOFeatureDeltaImpl)featureDelta).apply(revision); @@ -307,7 +311,6 @@ public class CDORevisionDeltaImpl implements InternalCDORevisionDelta @Override public String toString() { - return MessageFormat.format("CDORevisionDelta[{0}@{1}v{2} -> v{3}]", eClass.getName(), cdoID, originVersion, - dirtyVersion); + return MessageFormat.format("CDORevisionDelta[{0}@{1}:{2}v{3}]", eClass.getName(), id, branch.getID(), version); } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/CDOBranchUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/CDOBranchUtil.java new file mode 100644 index 0000000000..8f1abf0b1a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/CDOBranchUtil.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2004 - 2009 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.spi.common.branch; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.internal.common.branch.CDOBranchManagerImpl; +import org.eclipse.emf.cdo.internal.common.branch.CDOBranchPointImpl; +import org.eclipse.emf.cdo.internal.common.branch.CDOBranchVersionImpl; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public final class CDOBranchUtil +{ + private CDOBranchUtil() + { + } + + public static InternalCDOBranchManager createBranchManager() + { + return new CDOBranchManagerImpl(); + } + + public static CDOBranchPoint createBranchPoint(CDOBranch branch, long timeStamp) + { + return new CDOBranchPointImpl(branch, timeStamp); + } + + public static CDOBranchPoint createBranchPoint(CDOBranchPoint source) + { + return createBranchPoint(source.getBranch(), source.getTimeStamp()); + } + + public static CDOBranchVersion createBranchVersion(CDOBranch branch, int version) + { + return new CDOBranchVersionImpl(branch, version); + } + + public static CDOBranchVersion createBranchVersion(CDOBranchVersion source) + { + return createBranchVersion(source.getBranch(), source.getVersion()); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranch.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranch.java new file mode 100644 index 0000000000..5065cee5f9 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranch.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2004 - 2009 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.spi.common.branch; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader.BranchInfo; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface InternalCDOBranch extends CDOBranch +{ + public boolean isProxy(); + + public InternalCDOBranchManager getBranchManager(); + + public InternalCDOBranch[] getBranches(); + + public InternalCDOBranch getBranch(String path); + + public InternalCDOBranch createBranch(String name, long timeStamp); + + public InternalCDOBranch createBranch(String name); + + public BranchInfo getBranchInfo(); + + public void setBranchInfo(String name, InternalCDOBranch baseBranch, long baseTimeStamp); + + public void addChild(InternalCDOBranch branch); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java new file mode 100644 index 0000000000..ccc6737d29 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/InternalCDOBranchManager.java @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2004 - 2009 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.spi.common.branch; + +import org.eclipse.emf.cdo.common.CDOTimeProvider; +import org.eclipse.emf.cdo.common.branch.CDOBranchManager; +import org.eclipse.emf.cdo.common.io.CDODataInput; +import org.eclipse.emf.cdo.common.io.CDODataOutput; + +import org.eclipse.net4j.util.lifecycle.ILifecycle; + +import java.io.IOException; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public interface InternalCDOBranchManager extends CDOBranchManager, ILifecycle +{ + public BranchLoader getBranchLoader(); + + public void setBranchLoader(BranchLoader branchLoader); + + public CDOTimeProvider getTimeProvider(); + + public void setTimeProvider(CDOTimeProvider timeProvider); + + public void initMainBranch(long timestamp); + + public InternalCDOBranch getMainBranch(); + + public InternalCDOBranch getBranch(int branchID); + + public InternalCDOBranch getBranch(int id, String name, long baseTimeStamp, InternalCDOBranch base); + + public InternalCDOBranch getBranch(String path); + + public InternalCDOBranch createBranch(String name, InternalCDOBranch baseBranch, long baseTimeStamp); + + public void handleBranchCreated(InternalCDOBranch branch); + + /** + * @author Eike Stepper + * @since 3.0 + */ + public interface BranchLoader + { + public int createBranch(BranchInfo branchInfo); + + public BranchInfo loadBranch(int branchID); + + public SubBranchInfo[] loadSubBranches(int branchID); + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static final class BranchInfo + { + private String name; + + private int baseBranchID; + + private long baseTimeStamp; + + public BranchInfo(String name, int baseBranchID, long baseTimeStamp) + { + this.name = name; + this.baseBranchID = baseBranchID; + this.baseTimeStamp = baseTimeStamp; + } + + public BranchInfo(CDODataInput in) throws IOException + { + name = in.readString(); + baseBranchID = in.readInt(); + baseTimeStamp = in.readLong(); + } + + public void write(CDODataOutput out) throws IOException + { + out.writeString(name); + out.writeInt(baseBranchID); + out.writeLong(baseTimeStamp); + } + + public String getName() + { + return name; + } + + public int getBaseBranchID() + { + return baseBranchID; + } + + public long getBaseTimeStamp() + { + return baseTimeStamp; + } + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static final class SubBranchInfo + { + private int id; + + private String name; + + private long baseTimeStamp; + + public SubBranchInfo(int id, String name, long baseTimeStamp) + { + this.id = id; + this.name = name; + this.baseTimeStamp = baseTimeStamp; + } + + public SubBranchInfo(CDODataInput in) throws IOException + { + id = in.readInt(); + name = in.readString(); + baseTimeStamp = in.readLong(); + } + + public void write(CDODataOutput out) throws IOException + { + out.writeInt(id); + out.writeString(name); + out.writeLong(baseTimeStamp); + } + + public int getID() + { + return id; + } + + public String getName() + { + return name; + } + + public long getBaseTimeStamp() + { + return baseTimeStamp; + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java index 3aaf9605eb..9741d7e02d 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/AbstractCDORevision.java @@ -13,41 +13,12 @@ */ package org.eclipse.emf.cdo.spi.common.revision; -import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.id.CDOIDProvider; -import org.eclipse.emf.cdo.common.id.CDOIDTemp; -import org.eclipse.emf.cdo.common.id.CDOIDUtil; -import org.eclipse.emf.cdo.common.io.CDODataInput; -import org.eclipse.emf.cdo.common.io.CDODataOutput; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.model.CDOClassInfo; -import org.eclipse.emf.cdo.common.model.CDOClassifierRef; -import org.eclipse.emf.cdo.common.model.CDOModelUtil; -import org.eclipse.emf.cdo.common.model.CDOType; -import org.eclipse.emf.cdo.common.revision.CDOList; -import org.eclipse.emf.cdo.common.revision.CDOListFactory; -import org.eclipse.emf.cdo.common.revision.CDOReferenceAdjuster; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionData; -import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; -import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDeltaUtil; -import org.eclipse.emf.cdo.internal.common.bundle.OM; -import org.eclipse.emf.cdo.internal.common.messages.Messages; - -import org.eclipse.net4j.util.om.trace.ContextTracer; -import org.eclipse.net4j.util.om.trace.PerfTracer; import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EClassifier; -import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.InternalEObject.EStore; -import org.eclipse.emf.ecore.util.FeatureMap; -import org.eclipse.emf.ecore.util.FeatureMapUtil; -import org.eclipse.emf.ecore.util.FeatureMap.Entry; - -import java.io.IOException; -import java.text.MessageFormat; -import java.util.Map; /** * @author Eike Stepper @@ -55,323 +26,30 @@ import java.util.Map; */ public abstract class AbstractCDORevision implements InternalCDORevision { - private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, AbstractCDORevision.class); - - private static final PerfTracer READING = new PerfTracer(OM.PERF_REVISION_READING, AbstractCDORevision.class); - - private static final PerfTracer WRITING = new PerfTracer(OM.PERF_REVISION_WRITING, AbstractCDORevision.class); - - private static final byte UNSET = 0; - - private static final byte SET_NULL = 1; - - private static final byte SET_NOT_NULL = 2; - - private CDOClassInfo classInfo; - - private CDOID id; - - private int version; - - private long created; - - private long revised; - - private CDOID resourceID; - - private Object containerID; - - private int containingFeatureID; - - /** - * @since 3.0 - */ - public AbstractCDORevision(EClass eClass) - { - if (eClass != null) - { - if (eClass.isAbstract()) - { - throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.0"), eClass)); //$NON-NLS-1$ - } - - classInfo = CDOModelUtil.getClassInfo(eClass); - version = 0; - created = UNSPECIFIED_DATE; - revised = UNSPECIFIED_DATE; - resourceID = CDOID.NULL; - containerID = CDOID.NULL; - containingFeatureID = 0; - initValues(classInfo.getAllPersistentFeatures()); - } - } - - protected AbstractCDORevision(AbstractCDORevision source) - { - classInfo = source.classInfo; - id = source.id; - version = source.version; - created = source.created; - revised = source.revised; // == UNSPECIFIED - resourceID = source.resourceID; - containerID = source.containerID; - containingFeatureID = source.containingFeatureID; - } - - /** - * @since 3.0 - */ - public void read(CDODataInput in) throws IOException - { - READING.start(this); - EClassifier classifier = in.readCDOClassifierRefAndResolve(); - classInfo = CDOModelUtil.getClassInfo((EClass)classifier); - - id = in.readCDOID(); - version = in.readInt(); - if (!id.isTemporary()) - { - created = in.readLong(); - revised = in.readLong(); - } - - resourceID = in.readCDOID(); - containerID = in.readCDOID(); - containingFeatureID = in.readInt(); - if (TRACER.isEnabled()) - { - TRACER - .format( - "Reading revision: ID={0}, className={1}, version={2}, created={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$ - id, getEClass().getName(), version, created, revised, resourceID, containerID, containingFeatureID); - } - - readValues(in); - READING.stop(this); - } - - public void write(CDODataOutput out, int referenceChunk) throws IOException - { - EClass eClass = getEClass(); - CDOClassifierRef classRef = new CDOClassifierRef(eClass); - if (TRACER.isEnabled()) - { - TRACER - .format( - "Writing revision: ID={0}, className={1}, version={2}, created={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$ - id, eClass.getName(), getVersion(), created, revised, resourceID, containerID, containingFeatureID); - } - - WRITING.start(this); - - out.writeCDOClassifierRef(classRef); - out.writeCDOID(id); - out.writeInt(getVersion()); - if (!id.isTemporary()) - { - out.writeLong(created); - out.writeLong(revised); - } - - out.writeCDOID(resourceID); - out.writeCDOID(out.getIDProvider().provideCDOID(containerID)); - out.writeInt(containingFeatureID); - writeValues(out, referenceChunk); - WRITING.stop(this); - } - - /** - * @see #write(CDODataOutput, int) - * @since 3.0 - */ - public void convertEObjects(CDOIDProvider idProvider) - { - if (!(containerID instanceof CDOID)) - { - containerID = idProvider.provideCDOID(containerID); - } - - EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); - for (int i = 0; i < features.length; i++) - { - EStructuralFeature feature = features[i]; - if (feature.isMany()) - { - CDOList list = getValueAsList(i); - if (list != null) - { - boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature); - for (int j = 0; j < list.size(); j++) - { - Object value = list.get(j, false); - EStructuralFeature innerFeature = feature; // Prepare for possible feature map - if (isFeatureMap) - { - Entry entry = (FeatureMap.Entry)value; - innerFeature = entry.getEStructuralFeature(); - value = entry.getValue(); - } - - if (value != null && innerFeature instanceof EReference) - { - CDOID newValue = idProvider.provideCDOID(value); - if (newValue != value) - { - list.set(j, newValue); - } - } - } - } - } - else - { - checkNoFeatureMap(feature); - Object value = getValue(i); - if (value != null && feature instanceof EReference) - { - CDOID newValue = idProvider.provideCDOID(value); - if (newValue != value) - { - setValue(i, newValue); - } - } - } - } - } - - /** - * @since 3.0 - */ - public CDOClassInfo getClassInfo() - { - return classInfo; - } - public EClass getEClass() { - return classInfo.getEClass(); - } - - public CDOID getID() - { - return id; - } - - public void setID(CDOID id) - { - if (CDOIDUtil.isNull(id)) - { - throw new IllegalArgumentException(Messages.getString("AbstractCDORevision.1")); //$NON-NLS-1$ - } - - if (TRACER.isEnabled()) - { - TRACER.format("Setting ID: {0}", id); - } - - this.id = id; - } - - public int getVersion() - { - return version < 0 ? -version : version; - } - - public void setVersion(int version) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting version for {0}: v{1}", this, version); - } - - this.version = version; - } - - public boolean isTransactional() - { - return version < 0; - } - - /** - * @since 3.0 - */ - public int setTransactional(boolean on) - { - if (on) - { - version = -(version + 1); - } - else + CDOClassInfo classInfo = getClassInfo(); + if (classInfo != null) { - version = Math.abs(version); + return classInfo.getEClass(); } - if (TRACER.isEnabled()) - { - TRACER.format("Setting transactional={0} for {1}", on, this); - } - - return version; - } - - public long getCreated() - { - return created; - } - - public void setCreated(long created) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting created {0}: {1,date} {1,time}", this, created); - } - - this.created = created; - } - - public long getRevised() - { - return revised; - } - - public void setRevised(long revised) - { - if (revised != UNSPECIFIED_DATE && revised < Math.max(0, created)) - { - throw new IllegalArgumentException("created=" + created + ", revised=" + revised); - } - - if (TRACER.isEnabled()) - { - TRACER.format("Setting revised {0}: {1,date} {1,time}", this, revised); - } - - this.revised = revised; - } - - public boolean isCurrent() - { - return revised == UNSPECIFIED_DATE; - } - - public boolean isValid(long timeStamp) - { - return (revised == UNSPECIFIED_DATE || revised >= timeStamp) && timeStamp >= created; + return null; } public boolean isResourceNode() { - return classInfo.isResourceNode(); + return getClassInfo().isResourceNode(); } public boolean isResourceFolder() { - return classInfo.isResourceFolder(); + return getClassInfo().isResourceFolder(); } public boolean isResource() { - return classInfo.isResource(); + return getClassInfo().isResource(); } public CDORevisionData data() @@ -384,369 +62,52 @@ public abstract class AbstractCDORevision implements InternalCDORevision return this; } - public InternalCDORevisionDelta compare(CDORevision origin) - { - return (InternalCDORevisionDelta)CDORevisionDeltaUtil.create(origin, this); - } - - public void merge(CDORevisionDelta delta) - { - CDORevisionMerger applier = new CDORevisionMerger(); - applier.merge(this, delta); - } - - public CDOID getResourceID() - { - return resourceID; - } - - public void setResourceID(CDOID resourceID) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting resourceID {0}: {1}", this, resourceID); - } - - this.resourceID = resourceID; - } - - public Object getContainerID() - { - return containerID; - } - - public void setContainerID(Object containerID) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting containerID {0}: {1}", this, containerID); - } - - this.containerID = containerID; - } - - public int getContainingFeatureID() - { - return containingFeatureID; - } - - public void setContainingFeatureID(int containingFeatureID) - { - if (TRACER.isEnabled()) - { - TRACER.format("Setting containingFeatureID {0}: {1}", this, containingFeatureID); - } - - this.containingFeatureID = containingFeatureID; - } - - public int hashCode(EStructuralFeature feature) - { - return getValue(feature).hashCode(); - } - - public Object get(EStructuralFeature feature, int index) - { - if (feature.isMany() && index != EStore.NO_INDEX) - { - return getList(feature).get(index); - } - - return getValue(feature); - } - - public boolean contains(EStructuralFeature feature, Object value) - { - return getList(feature).contains(value); - } - - public int indexOf(EStructuralFeature feature, Object value) - { - return getList(feature).indexOf(value); - } - - public boolean isEmpty(EStructuralFeature feature) - { - return getList(feature).isEmpty(); - } - - public int lastIndexOf(EStructuralFeature feature, Object value) - { - return getList(feature).lastIndexOf(value); - } - - public int size(EStructuralFeature feature) - { - return getList(feature).size(); - } - - public Object[] toArray(EStructuralFeature feature) - { - if (!feature.isMany()) - { - throw new IllegalStateException("!feature.isMany()"); - } - - return getList(feature).toArray(); - } - - public <T> T[] toArray(EStructuralFeature feature, T[] array) - { - if (!feature.isMany()) - { - throw new IllegalStateException("!feature.isMany()"); - } - - return getList(feature).toArray(array); - } - - public void add(EStructuralFeature feature, int index, Object value) - { - getList(feature).add(index, value); - } - - public void clear(EStructuralFeature feature) - { - setValue(feature, null); - } - - public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex) + /** + * @since 3.0 + */ + public boolean isHistorical() { - return getList(feature).move(targetIndex, sourceIndex); + return getRevised() != UNSPECIFIED_DATE; } - public Object remove(EStructuralFeature feature, int index) + public boolean isValid(long timeStamp) { - return getList(feature).remove(index); + long revised = getRevised(); + return (revised == UNSPECIFIED_DATE || revised >= timeStamp) && timeStamp >= getTimeStamp(); } - public Object set(EStructuralFeature feature, int index, Object value) + /** + * @since 3.0 + */ + public void adjustForCommit(CDOBranch branch, long timeStamp) { - if (feature.isMany()) + if (branch.equals(getBranch())) { - return getList(feature).set(index, value); + // Same branch, increase version + setVersion(getVersion() + 1); } - - return setValue(feature, value); - } - - public void unset(EStructuralFeature feature) - { - setValue(feature, null); - } - - public void adjustReferences(CDOReferenceAdjuster revisionAdjuster) - { - if (TRACER.isEnabled()) + else { - TRACER.format("Adjusting references for revision {0}", this); + // Different branch, start with v1 + setVersion(FIRST_VERSION); } - resourceID = (CDOID)revisionAdjuster.adjustReference(resourceID); - containerID = revisionAdjuster.adjustReference(containerID); - - EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); - for (int i = 0; i < features.length; i++) - { - EStructuralFeature feature = features[i]; - if (feature instanceof EReference || FeatureMapUtil.isFeatureMap(feature)) - { - if (feature.isMany()) - { - InternalCDOList list = (InternalCDOList)getValueAsList(i); - if (list != null) - { - list.adjustReferences(revisionAdjuster, feature); - } - } - else - { - CDOType type = CDOModelUtil.getType(feature); - setValue(i, type.adjustReferences(revisionAdjuster, getValue(i))); - } - } - } + setBranchPoint(branch.getPoint(timeStamp)); + setRevised(UNSPECIFIED_DATE); } @Override public String toString() { - return getEClass().getName() + "@" + id + "v" + version; - } - - public Object getValue(EStructuralFeature feature) - { - int featureIndex = classInfo.getFeatureIndex(feature); - return getValue(featureIndex); - } - - public Object setValue(EStructuralFeature feature, Object value) - { - int featureIndex = classInfo.getFeatureIndex(feature); - - try - { - Object old = getValue(featureIndex); - setValue(featureIndex, value); - return old; - } - catch (ArrayIndexOutOfBoundsException ex) - { - throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.20"), feature, - classInfo), ex); - } - } - - public CDOList getList(EStructuralFeature feature) - { - return getList(feature, 0); - } - - public CDOList getList(EStructuralFeature feature, int size) - { - int featureIndex = classInfo.getFeatureIndex(feature); - CDOList list = (CDOList)getValue(featureIndex); - if (list == null && size != -1) - { - list = CDOListFactory.DEFAULT.createList(size, 0, 0); - setValue(featureIndex, list); - } - - return list; - } - - public void setList(EStructuralFeature feature, InternalCDOList list) - { - int featureIndex = classInfo.getFeatureIndex(feature); - setValue(featureIndex, list); - } - - protected abstract void initValues(EStructuralFeature[] allPersistentFeatures); - - protected abstract Object getValue(int featureIndex); - - protected abstract void setValue(int featureIndex, Object value); - - private CDOList getValueAsList(int i) - { - return (CDOList)getValue(i); - } - - private void writeValues(CDODataOutput out, int referenceChunk) throws IOException - { - EClass owner = getEClass(); - EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); - for (int i = 0; i < features.length; i++) - { - EStructuralFeature feature = features[i]; - Object value = getValue(i); - if (value == null) - { - // Feature is NOT set - out.writeByte(UNSET); - continue; - } - - // Feature IS set - if (value == CDORevisionData.NIL) - { - // Feature IS null - out.writeByte(SET_NULL); - continue; - } - - // Feature is NOT null - out.writeByte(SET_NOT_NULL); - if (feature.isMany()) - { - CDOList list = (CDOList)value; - out.writeCDOList(owner, feature, list, referenceChunk); - } - else - { - checkNoFeatureMap(feature); - if (value != null && feature instanceof EReference) - { - value = out.getIDProvider().provideCDOID(value); - } - - if (TRACER.isEnabled()) - { - TRACER.format("Writing feature {0}: {1}", feature.getName(), value); - } - - out.writeCDOFeatureValue(feature, value); - } - } - } - - private void readValues(CDODataInput in) throws IOException - { - EClass owner = getEClass(); - EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); - initValues(features); - for (int i = 0; i < features.length; i++) - { - Object value; - EStructuralFeature feature = features[i]; - byte unsetState = in.readByte(); - switch (unsetState) - { - case UNSET: - continue; - - case SET_NULL: - setValue(i, CDORevisionData.NIL); - continue; - } - - if (feature.isMany()) - { - value = in.readCDOList(owner, feature); - } - else - { - value = in.readCDOFeatureValue(feature); - if (TRACER.isEnabled()) - { - TRACER.format("Read feature {0}: {1}", feature.getName(), value); - } - } - - setValue(i, value); - } - } - - public static void checkNoFeatureMap(EStructuralFeature feature) - { - if (FeatureMapUtil.isFeatureMap(feature)) - { - throw new UnsupportedOperationException("Single-valued feature maps not yet handled"); - } - } + EClass eClass = getEClass(); + String name = eClass == null ? "Revision" : eClass.getName(); - public static Object remapID(Object value, Map<CDOIDTemp, CDOID> idMappings) - { - if (value instanceof CDOIDTemp) + CDOBranch branch = getBranch(); + if (branch == null) { - CDOIDTemp oldID = (CDOIDTemp)value; - if (!oldID.isNull()) - { - CDOID newID = idMappings.get(oldID); - if (newID == null) - { - throw new IllegalStateException(MessageFormat.format(Messages.getString("AbstractCDORevision.2"), oldID)); - } - - if (TRACER.isEnabled()) - { - TRACER.format("Adjusting ID: {0} --> {1}", oldID, newID); - } - - return newID; - } + return name + "@" + getID() + "v" + getVersion(); } - return value; + return name + "@" + getID() + ":" + branch.getID() + "v" + getVersion(); } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java new file mode 100644 index 0000000000..5b4849836e --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/BaseCDORevision.java @@ -0,0 +1,712 @@ +/** + * Copyright (c) 2004 - 2009 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 + * Simon McDuff - bug 201266 + * Simon McDuff - bug 212958 + * Simon McDuff - bug 213402 + */ +package org.eclipse.emf.cdo.spi.common.revision; + +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.common.id.CDOIDProvider; +import org.eclipse.emf.cdo.common.id.CDOIDTemp; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.io.CDODataInput; +import org.eclipse.emf.cdo.common.io.CDODataOutput; +import org.eclipse.emf.cdo.common.model.CDOClassInfo; +import org.eclipse.emf.cdo.common.model.CDOClassifierRef; +import org.eclipse.emf.cdo.common.model.CDOModelUtil; +import org.eclipse.emf.cdo.common.model.CDOType; +import org.eclipse.emf.cdo.common.revision.CDOList; +import org.eclipse.emf.cdo.common.revision.CDOListFactory; +import org.eclipse.emf.cdo.common.revision.CDOReferenceAdjuster; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionData; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDeltaUtil; +import org.eclipse.emf.cdo.internal.common.bundle.OM; +import org.eclipse.emf.cdo.internal.common.messages.Messages; +import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; + +import org.eclipse.net4j.util.om.trace.ContextTracer; +import org.eclipse.net4j.util.om.trace.PerfTracer; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.InternalEObject.EStore; +import org.eclipse.emf.ecore.util.FeatureMap; +import org.eclipse.emf.ecore.util.FeatureMapUtil; +import org.eclipse.emf.ecore.util.FeatureMap.Entry; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Map; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public abstract class BaseCDORevision extends AbstractCDORevision +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REVISION, BaseCDORevision.class); + + private static final PerfTracer READING = new PerfTracer(OM.PERF_REVISION_READING, BaseCDORevision.class); + + private static final PerfTracer WRITING = new PerfTracer(OM.PERF_REVISION_WRITING, BaseCDORevision.class); + + private static final byte UNSET = 0; + + private static final byte SET_NULL = 1; + + private static final byte SET_NOT_NULL = 2; + + private CDOClassInfo classInfo; + + private CDOID id; + + private CDOBranchPoint branchPoint; + + private int version; + + private long revised; + + private CDOID resourceID; + + private Object containerID; + + private int containingFeatureID; + + /** + * @since 3.0 + */ + public BaseCDORevision(EClass eClass) + { + if (eClass != null) + { + if (eClass.isAbstract()) + { + throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.0"), eClass)); //$NON-NLS-1$ + } + + classInfo = CDOModelUtil.getClassInfo(eClass); + version = UNSPECIFIED_VERSION; + revised = UNSPECIFIED_DATE; + resourceID = CDOID.NULL; + containerID = CDOID.NULL; + containingFeatureID = 0; + initValues(classInfo.getAllPersistentFeatures()); + } + } + + protected BaseCDORevision(BaseCDORevision source) + { + classInfo = source.classInfo; + id = source.id; + branchPoint = source.branchPoint; + version = source.version; + revised = source.revised; // == UNSPECIFIED_DATE + resourceID = source.resourceID; + containerID = source.containerID; + containingFeatureID = source.containingFeatureID; + } + + /** + * @since 3.0 + */ + public void read(CDODataInput in) throws IOException + { + READING.start(this); + EClassifier classifier = in.readCDOClassifierRefAndResolve(); + classInfo = CDOModelUtil.getClassInfo((EClass)classifier); + + id = in.readCDOID(); + branchPoint = in.readCDOBranchPoint(); + version = in.readInt(); + if (!id.isTemporary()) + { + revised = in.readLong(); + } + + resourceID = in.readCDOID(); + containerID = in.readCDOID(); + containingFeatureID = in.readInt(); + if (TRACER.isEnabled()) + { + TRACER + .format( + "Reading revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$ + id, getEClass().getName(), version, branchPoint, revised, resourceID, containerID, containingFeatureID); + } + + readValues(in); + READING.stop(this); + } + + public void write(CDODataOutput out, int referenceChunk) throws IOException + { + EClass eClass = getEClass(); + CDOClassifierRef classRef = new CDOClassifierRef(eClass); + if (TRACER.isEnabled()) + { + TRACER + .format( + "Writing revision: ID={0}, className={1}, version={2}, branchPoint={3}, revised={4}, resource={5}, container={6}, featureID={7}", //$NON-NLS-1$ + id, eClass.getName(), getVersion(), branchPoint, revised, resourceID, containerID, containingFeatureID); + } + + WRITING.start(this); + + out.writeCDOClassifierRef(classRef); + out.writeCDOID(id); + out.writeCDOBranchPoint(branchPoint); + out.writeInt(getVersion()); + if (!id.isTemporary()) + { + out.writeLong(revised); + } + + out.writeCDOID(resourceID); + out.writeCDOID(out.getIDProvider().provideCDOID(containerID)); + out.writeInt(containingFeatureID); + writeValues(out, referenceChunk); + WRITING.stop(this); + } + + /** + * @see #write(CDODataOutput, int) + * @since 3.0 + */ + public void convertEObjects(CDOIDProvider idProvider) + { + if (!(containerID instanceof CDOID)) + { + containerID = idProvider.provideCDOID(containerID); + } + + EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); + for (int i = 0; i < features.length; i++) + { + EStructuralFeature feature = features[i]; + if (feature.isMany()) + { + CDOList list = getValueAsList(i); + if (list != null) + { + boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature); + for (int j = 0; j < list.size(); j++) + { + Object value = list.get(j, false); + EStructuralFeature innerFeature = feature; // Prepare for possible feature map + if (isFeatureMap) + { + Entry entry = (FeatureMap.Entry)value; + innerFeature = entry.getEStructuralFeature(); + value = entry.getValue(); + } + + if (value != null && innerFeature instanceof EReference) + { + CDOID newValue = idProvider.provideCDOID(value); + if (newValue != value) + { + list.set(j, newValue); + } + } + } + } + } + else + { + checkNoFeatureMap(feature); + Object value = getValue(i); + if (value != null && feature instanceof EReference) + { + CDOID newValue = idProvider.provideCDOID(value); + if (newValue != value) + { + setValue(i, newValue); + } + } + } + } + } + + /** + * @since 3.0 + */ + public CDOClassInfo getClassInfo() + { + return classInfo; + } + + public CDOID getID() + { + return id; + } + + public void setID(CDOID id) + { + if (CDOIDUtil.isNull(id)) + { + throw new IllegalArgumentException(Messages.getString("AbstractCDORevision.1")); //$NON-NLS-1$ + } + + if (TRACER.isEnabled()) + { + TRACER.format("Setting ID: {0}", id); + } + + this.id = id; + } + + /** + * @since 3.0 + */ + public CDOBranch getBranch() + { + if (branchPoint == null) + { + return null; + } + + return branchPoint.getBranch(); + } + + /** + * @since 3.0 + */ + public long getTimeStamp() + { + if (branchPoint == null) + { + return UNSPECIFIED_DATE; + } + + return branchPoint.getTimeStamp(); + } + + /** + * @since 3.0 + */ + public void setBranchPoint(CDOBranchPoint branchPoint) + { + branchPoint = CDOBranchUtil.createBranchPoint(branchPoint); + if (TRACER.isEnabled()) + { + TRACER.format("Setting branchPoint {0}: {1}", this, branchPoint); + } + + this.branchPoint = branchPoint; + } + + public int getVersion() + { + return version; + } + + public void setVersion(int version) + { + if (TRACER.isEnabled()) + { + TRACER.format("Setting version for {0}: v{1}", this, version); + } + + this.version = version; + } + + public long getRevised() + { + return revised; + } + + public void setRevised(long revised) + { + long created = branchPoint.getTimeStamp(); + if (revised != UNSPECIFIED_DATE && revised < Math.max(0, created)) + { + throw new IllegalArgumentException("revision=" + this + ", created=" + created + ", revised=" + revised); + } + + if (TRACER.isEnabled()) + { + TRACER.format("Setting revised {0}: {1,date} {1,time,HH:mm:ss:SSS}", this, revised); + } + + this.revised = revised; + } + + public InternalCDORevisionDelta compare(CDORevision origin) + { + return (InternalCDORevisionDelta)CDORevisionDeltaUtil.create(origin, this); + } + + public int compareTo(CDOBranchPoint o) + { + return branchPoint.compareTo(o); + } + + public void merge(CDORevisionDelta delta) + { + CDORevisionMerger applier = new CDORevisionMerger(); + applier.merge(this, delta); + } + + public CDOID getResourceID() + { + return resourceID; + } + + public void setResourceID(CDOID resourceID) + { + if (TRACER.isEnabled()) + { + TRACER.format("Setting resourceID {0}: {1}", this, resourceID); + } + + this.resourceID = resourceID; + } + + public Object getContainerID() + { + return containerID; + } + + public void setContainerID(Object containerID) + { + if (TRACER.isEnabled()) + { + TRACER.format("Setting containerID {0}: {1}", this, containerID); + } + + this.containerID = containerID; + } + + public int getContainingFeatureID() + { + return containingFeatureID; + } + + public void setContainingFeatureID(int containingFeatureID) + { + if (TRACER.isEnabled()) + { + TRACER.format("Setting containingFeatureID {0}: {1}", this, containingFeatureID); + } + + this.containingFeatureID = containingFeatureID; + } + + public int hashCode(EStructuralFeature feature) + { + return getValue(feature).hashCode(); + } + + public Object get(EStructuralFeature feature, int index) + { + if (feature.isMany() && index != EStore.NO_INDEX) + { + return getList(feature).get(index); + } + + return getValue(feature); + } + + public boolean contains(EStructuralFeature feature, Object value) + { + return getList(feature).contains(value); + } + + public int indexOf(EStructuralFeature feature, Object value) + { + return getList(feature).indexOf(value); + } + + public boolean isEmpty(EStructuralFeature feature) + { + return getList(feature).isEmpty(); + } + + public int lastIndexOf(EStructuralFeature feature, Object value) + { + return getList(feature).lastIndexOf(value); + } + + public int size(EStructuralFeature feature) + { + return getList(feature).size(); + } + + public Object[] toArray(EStructuralFeature feature) + { + if (!feature.isMany()) + { + throw new IllegalStateException("!feature.isMany()"); + } + + return getList(feature).toArray(); + } + + public <T> T[] toArray(EStructuralFeature feature, T[] array) + { + if (!feature.isMany()) + { + throw new IllegalStateException("!feature.isMany()"); + } + + return getList(feature).toArray(array); + } + + public void add(EStructuralFeature feature, int index, Object value) + { + getList(feature).add(index, value); + } + + public void clear(EStructuralFeature feature) + { + setValue(feature, null); + } + + public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex) + { + return getList(feature).move(targetIndex, sourceIndex); + } + + public Object remove(EStructuralFeature feature, int index) + { + return getList(feature).remove(index); + } + + public Object set(EStructuralFeature feature, int index, Object value) + { + if (feature.isMany()) + { + return getList(feature).set(index, value); + } + + return setValue(feature, value); + } + + public void unset(EStructuralFeature feature) + { + setValue(feature, null); + } + + public void adjustReferences(CDOReferenceAdjuster revisionAdjuster) + { + if (TRACER.isEnabled()) + { + TRACER.format("Adjusting references for revision {0}", this); + } + + resourceID = (CDOID)revisionAdjuster.adjustReference(resourceID); + containerID = revisionAdjuster.adjustReference(containerID); + + EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); + for (int i = 0; i < features.length; i++) + { + EStructuralFeature feature = features[i]; + if (feature instanceof EReference || FeatureMapUtil.isFeatureMap(feature)) + { + if (feature.isMany()) + { + InternalCDOList list = (InternalCDOList)getValueAsList(i); + if (list != null) + { + list.adjustReferences(revisionAdjuster, feature); + } + } + else + { + CDOType type = CDOModelUtil.getType(feature); + setValue(i, type.adjustReferences(revisionAdjuster, getValue(i))); + } + } + } + } + + public Object getValue(EStructuralFeature feature) + { + int featureIndex = classInfo.getFeatureIndex(feature); + return getValue(featureIndex); + } + + public Object setValue(EStructuralFeature feature, Object value) + { + int featureIndex = classInfo.getFeatureIndex(feature); + + try + { + Object old = getValue(featureIndex); + setValue(featureIndex, value); + return old; + } + catch (ArrayIndexOutOfBoundsException ex) + { + throw new IllegalArgumentException(MessageFormat.format(Messages.getString("AbstractCDORevision.20"), feature, + classInfo), ex); + } + } + + public CDOList getList(EStructuralFeature feature) + { + return getList(feature, 0); + } + + public CDOList getList(EStructuralFeature feature, int size) + { + int featureIndex = classInfo.getFeatureIndex(feature); + CDOList list = (CDOList)getValue(featureIndex); + if (list == null && size != -1) + { + list = CDOListFactory.DEFAULT.createList(size, 0, 0); + setValue(featureIndex, list); + } + + return list; + } + + public void setList(EStructuralFeature feature, InternalCDOList list) + { + int featureIndex = classInfo.getFeatureIndex(feature); + setValue(featureIndex, list); + } + + protected abstract void initValues(EStructuralFeature[] allPersistentFeatures); + + protected abstract Object getValue(int featureIndex); + + protected abstract void setValue(int featureIndex, Object value); + + private CDOList getValueAsList(int i) + { + return (CDOList)getValue(i); + } + + private void writeValues(CDODataOutput out, int referenceChunk) throws IOException + { + EClass owner = getEClass(); + EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); + for (int i = 0; i < features.length; i++) + { + EStructuralFeature feature = features[i]; + Object value = getValue(i); + if (value == null) + { + // Feature is NOT set + out.writeByte(UNSET); + continue; + } + + // Feature IS set + if (value == CDORevisionData.NIL) + { + // Feature IS null + out.writeByte(SET_NULL); + continue; + } + + // Feature is NOT null + out.writeByte(SET_NOT_NULL); + if (feature.isMany()) + { + CDOList list = (CDOList)value; + out.writeCDOList(owner, feature, list, referenceChunk); + } + else + { + checkNoFeatureMap(feature); + if (value != null && feature instanceof EReference) + { + value = out.getIDProvider().provideCDOID(value); + } + + if (TRACER.isEnabled()) + { + TRACER.format("Writing feature {0}: {1}", feature.getName(), value); + } + + out.writeCDOFeatureValue(feature, value); + } + } + } + + private void readValues(CDODataInput in) throws IOException + { + EClass owner = getEClass(); + EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); + initValues(features); + for (int i = 0; i < features.length; i++) + { + Object value; + EStructuralFeature feature = features[i]; + byte unsetState = in.readByte(); + switch (unsetState) + { + case UNSET: + continue; + + case SET_NULL: + setValue(i, CDORevisionData.NIL); + continue; + } + + if (feature.isMany()) + { + value = in.readCDOList(owner, feature); + } + else + { + value = in.readCDOFeatureValue(feature); + if (TRACER.isEnabled()) + { + TRACER.format("Read feature {0}: {1}", feature.getName(), value); + } + } + + setValue(i, value); + } + } + + public static void checkNoFeatureMap(EStructuralFeature feature) + { + if (FeatureMapUtil.isFeatureMap(feature)) + { + throw new UnsupportedOperationException("Single-valued feature maps not yet handled"); + } + } + + public static Object remapID(Object value, Map<CDOIDTemp, CDOID> idMappings) + { + if (value instanceof CDOIDTemp) + { + CDOIDTemp oldID = (CDOIDTemp)value; + if (!oldID.isNull()) + { + CDOID newID = idMappings.get(oldID); + if (newID == null) + { + throw new IllegalStateException(MessageFormat.format(Messages.getString("AbstractCDORevision.2"), oldID)); + } + + if (TRACER.isEnabled()) + { + TRACER.format("Adjusting ID: {0} --> {1}", oldID, newID); + } + + return newID; + } + } + + return value; + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java new file mode 100644 index 0000000000..df912654cc --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevision.java @@ -0,0 +1,302 @@ +/** + * Copyright (c) 2004 - 2009 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.spi.common.revision; + +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.common.id.CDOIDProvider; +import org.eclipse.emf.cdo.common.io.CDODataInput; +import org.eclipse.emf.cdo.common.io.CDODataOutput; +import org.eclipse.emf.cdo.common.model.CDOClassInfo; +import org.eclipse.emf.cdo.common.revision.CDOList; +import org.eclipse.emf.cdo.common.revision.CDOReferenceAdjuster; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionData; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EStructuralFeature; + +import java.io.IOException; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public abstract class DelegatingCDORevision implements InternalCDORevision +{ + public DelegatingCDORevision() + { + } + + public abstract InternalCDORevision getDelegate(); + + public int compareTo(CDOBranchPoint o) + { + return getDelegate().compareTo(o); + } + + public void adjustReferences(CDOReferenceAdjuster revisionAdjuster) + { + getDelegate().adjustReferences(revisionAdjuster); + } + + public long getTimeStamp() + { + return getDelegate().getTimeStamp(); + } + + public CDOBranch getBranch() + { + return getDelegate().getBranch(); + } + + public boolean isHistorical() + { + return getDelegate().isHistorical(); + } + + public CDOID getID() + { + return getDelegate().getID(); + } + + public CDORevision revision() + { + return getDelegate().revision(); + } + + public CDOID getResourceID() + { + return getDelegate().getResourceID(); + } + + public Object getContainerID() + { + return getDelegate().getContainerID(); + } + + public int getContainingFeatureID() + { + return getDelegate().getContainingFeatureID(); + } + + public Object get(EStructuralFeature feature, int index) + { + return getDelegate().get(feature, index); + } + + public EClass getEClass() + { + return getDelegate().getEClass(); + } + + public int getVersion() + { + return getDelegate().getVersion(); + } + + public int size(EStructuralFeature feature) + { + return getDelegate().size(feature); + } + + public long getRevised() + { + return getDelegate().getRevised(); + } + + public boolean isEmpty(EStructuralFeature feature) + { + return getDelegate().isEmpty(feature); + } + + public boolean isValid(long timeStamp) + { + return getDelegate().isValid(timeStamp); + } + + public CDOClassInfo getClassInfo() + { + return getDelegate().getClassInfo(); + } + + public void setID(CDOID id) + { + getDelegate().setID(id); + } + + public boolean contains(EStructuralFeature feature, Object value) + { + return getDelegate().contains(feature, value); + } + + public boolean isResourceNode() + { + return getDelegate().isResourceNode(); + } + + public void setVersion(int version) + { + getDelegate().setVersion(version); + } + + public boolean isResourceFolder() + { + return getDelegate().isResourceFolder(); + } + + public int indexOf(EStructuralFeature feature, Object value) + { + return getDelegate().indexOf(feature, value); + } + + public boolean isResource() + { + return getDelegate().isResource(); + } + + public void setBranchPoint(CDOBranchPoint branchPoint) + { + getDelegate().setBranchPoint(branchPoint); + } + + public void adjustForCommit(CDOBranch branch, long timeStamp) + { + getDelegate().adjustForCommit(branch, timeStamp); + } + + public CDORevisionData data() + { + return getDelegate().data(); + } + + public int lastIndexOf(EStructuralFeature feature, Object value) + { + return getDelegate().lastIndexOf(feature, value); + } + + public void setRevised(long revised) + { + getDelegate().setRevised(revised); + } + + public CDORevisionDelta compare(CDORevision origin) + { + return getDelegate().compare(origin); + } + + public void setResourceID(CDOID resourceID) + { + getDelegate().setResourceID(resourceID); + } + + public void merge(CDORevisionDelta delta) + { + getDelegate().merge(delta); + } + + public <T> T[] toArray(EStructuralFeature feature, T[] array) + { + return getDelegate().toArray(feature, array); + } + + public void setContainerID(Object containerID) + { + getDelegate().setContainerID(containerID); + } + + public void setContainingFeatureID(int containingFeatureID) + { + getDelegate().setContainingFeatureID(containingFeatureID); + } + + public Object[] toArray(EStructuralFeature feature) + { + return getDelegate().toArray(feature); + } + + public void add(EStructuralFeature feature, int index, Object value) + { + getDelegate().add(feature, index, value); + } + + public int hashCode(EStructuralFeature feature) + { + return getDelegate().hashCode(feature); + } + + public void clear(EStructuralFeature feature) + { + getDelegate().clear(feature); + } + + public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex) + { + return getDelegate().move(feature, targetIndex, sourceIndex); + } + + public Object remove(EStructuralFeature feature, int index) + { + return getDelegate().remove(feature, index); + } + + public Object set(EStructuralFeature feature, int index, Object value) + { + return getDelegate().set(feature, index, value); + } + + public void unset(EStructuralFeature feature) + { + getDelegate().unset(feature); + } + + public Object getValue(EStructuralFeature feature) + { + return getDelegate().getValue(feature); + } + + public Object setValue(EStructuralFeature feature, Object value) + { + return getDelegate().setValue(feature, value); + } + + public void setList(EStructuralFeature feature, InternalCDOList list) + { + getDelegate().setList(feature, list); + } + + public CDOList getList(EStructuralFeature feature) + { + return getDelegate().getList(feature); + } + + public CDOList getList(EStructuralFeature feature, int size) + { + return getDelegate().getList(feature, size); + } + + public void read(CDODataInput in) throws IOException + { + getDelegate().read(in); + } + + public void write(CDODataOutput out, int referenceChunk) throws IOException + { + getDelegate().write(out, referenceChunk); + } + + public void convertEObjects(CDOIDProvider oidProvider) + { + getDelegate().convertEObjects(oidProvider); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevisionManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevisionManager.java new file mode 100644 index 0000000000..ef8d99261b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DelegatingCDORevisionManager.java @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2004 - 2009 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.spi.common.revision; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; +import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; + +import org.eclipse.net4j.util.lifecycle.Lifecycle; + +import org.eclipse.emf.ecore.EClass; + +import java.util.List; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public abstract class DelegatingCDORevisionManager extends Lifecycle implements InternalCDORevisionManager +{ + public DelegatingCDORevisionManager() + { + } + + public InternalCDORevisionCache getCache() + { + return getDelegate().getCache(); + } + + public void setCache(CDORevisionCache cache) + { + getDelegate().setCache(cache); + } + + public void setFactory(CDORevisionFactory factory) + { + getDelegate().setFactory(factory); + } + + public CDORevisionFactory getFactory() + { + return getDelegate().getFactory(); + } + + public RevisionLoader getRevisionLoader() + { + return getDelegate().getRevisionLoader(); + } + + public void setRevisionLoader(RevisionLoader revisionLoader) + { + getDelegate().setRevisionLoader(revisionLoader); + } + + public RevisionLocker getRevisionLocker() + { + return getDelegate().getRevisionLocker(); + } + + public void setRevisionLocker(RevisionLocker revisionLocker) + { + getDelegate().setRevisionLocker(revisionLocker); + } + + public boolean isSupportingBranches() + { + return getDelegate().isSupportingBranches(); + } + + public void setSupportingBranches(boolean on) + { + getDelegate().setSupportingBranches(on); + } + + public boolean addRevision(CDORevision revision) + { + return getDelegate().addRevision(revision); + } + + public boolean containsRevision(CDOID id, CDOBranchPoint branchPoint) + { + return getDelegate().containsRevision(id, branchPoint); + } + + public boolean containsRevisionByVersion(CDOID id, CDOBranchVersion branchVersion) + { + return getDelegate().containsRevisionByVersion(id, branchVersion); + } + + public EClass getObjectType(CDOID id) + { + return getDelegate().getObjectType(id); + } + + public CDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk, + boolean loadOnDemand) + { + return getDelegate().getRevisionByVersion(id, branchVersion, referenceChunk, loadOnDemand); + } + + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean loadOnDemand) + { + return getDelegate().getRevision(id, branchPoint, referenceChunk, prefetchDepth, loadOnDemand); + } + + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean loadOnDemand, SyntheticCDORevision[] synthetics) + { + return getDelegate().getRevision(id, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, synthetics); + } + + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, + int prefetchDepth, boolean loadOnDemand) + { + return getDelegate().getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand); + } + + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, + int prefetchDepth, boolean loadOnDemand, SyntheticCDORevision[] synthetics) + { + return getDelegate().getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, loadOnDemand, synthetics); + } + + public void reviseLatest(CDOID id, CDOBranch branch) + { + getDelegate().reviseLatest(id, branch); + } + + public void reviseVersion(CDOID id, CDOBranchVersion branchVersion, long timeStamp) + { + getDelegate().reviseVersion(id, branchVersion, timeStamp); + } + + @Override + protected void doActivate() throws Exception + { + if (isDelegatingLifecycle()) + { + getDelegate().activate(); + } + } + + @Override + protected void doDeactivate() throws Exception + { + if (isDelegatingLifecycle()) + { + getDelegate().deactivate(); + } + } + + protected boolean isDelegatingLifecycle() + { + return true; + } + + protected abstract InternalCDORevisionManager getDelegate(); +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DetachedCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DetachedCDORevision.java new file mode 100644 index 0000000000..1037848a78 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/DetachedCDORevision.java @@ -0,0 +1,48 @@ +package org.eclipse.emf.cdo.spi.common.revision; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.id.CDOID; + +import java.text.MessageFormat; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public class DetachedCDORevision extends SyntheticCDORevision +{ + private int version; + + private long timeStamp; + + public DetachedCDORevision(CDOID id, CDOBranch branch, int version, long timeStamp) + { + super(id, branch); + this.version = version; + this.timeStamp = timeStamp; + } + + @Override + public final int getVersion() + { + return version; + } + + @Override + public long getTimeStamp() + { + return timeStamp; + } + + @Override + public long getRevised() + { + return UNSPECIFIED_DATE; + } + + @Override + public String toString() + { + return MessageFormat.format("DetachedCDORevision[{0}:{1}v{2}]", getID(), getBranch().getID(), version); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java index 74e18df90e..6fdc85cade 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevision.java @@ -11,6 +11,8 @@ */ package org.eclipse.emf.cdo.spi.common.revision; +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.common.id.CDOIDProvider; import org.eclipse.emf.cdo.common.io.CDODataInput; @@ -43,9 +45,7 @@ public interface InternalCDORevision extends CDORevision, CDORevisionData, CDORe /** * @since 3.0 */ - public int setTransactional(boolean on); - - public void setCreated(long created); + public void setBranchPoint(CDOBranchPoint branchPoint); public void setRevised(long revised); @@ -55,6 +55,11 @@ public interface InternalCDORevision extends CDORevision, CDORevisionData, CDORe public void setContainingFeatureID(int containingFeatureID); + /** + * @since 3.0 + */ + public void adjustForCommit(CDOBranch branch, long timeStamp); + public void add(EStructuralFeature feature, int index, Object value); public void clear(EStructuralFeature feature); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionDelta.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionDelta.java index 10825713ca..e295d354ee 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionDelta.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionDelta.java @@ -4,12 +4,13 @@ * 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.spi.common.revision; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.revision.CDOReferenceAdjuster; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; @@ -25,7 +26,13 @@ public interface InternalCDORevisionDelta extends CDORevisionDelta public void adjustReferences(CDOReferenceAdjuster idMappings); - public void setOriginVersion(int originVersion); + /** + * @since 3.0 + */ + public void setBranch(CDOBranch branch); - public void setDirtyVersion(int dirtyVersion); + /** + * @since 3.0 + */ + public void setVersion(int version); } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java index a37a92739e..15fb0735a3 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/InternalCDORevisionManager.java @@ -10,22 +10,31 @@ */ package org.eclipse.emf.cdo.spi.common.revision; +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; import org.eclipse.emf.cdo.common.revision.CDORevisionManager; import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; +import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCacheAdder; +import org.eclipse.emf.cdo.common.revision.cache.InternalCDORevisionCache; import org.eclipse.net4j.util.lifecycle.ILifecycle; -import java.util.Collection; import java.util.List; /** * @author Eike Stepper * @since 3.0 */ -public interface InternalCDORevisionManager extends CDORevisionManager, ILifecycle +public interface InternalCDORevisionManager extends CDORevisionManager, CDORevisionCacheAdder, ILifecycle { + public boolean isSupportingBranches(); + + public void setSupportingBranches(boolean on); + public RevisionLoader getRevisionLoader(); public void setRevisionLoader(RevisionLoader revisionLoader); @@ -38,35 +47,35 @@ public interface InternalCDORevisionManager extends CDORevisionManager, ILifecyc public void setFactory(CDORevisionFactory factory); - public CDORevisionCache getCache(); + public InternalCDORevisionCache getCache(); public void setCache(CDORevisionCache cache); - public void reviseLatest(CDOID id); + public void reviseLatest(CDOID id, CDOBranch branch); + + public void reviseVersion(CDOID id, CDOBranchVersion branchVersion, long timeStamp); + + public CDORevision getRevision(CDOID id, CDOBranchPoint branchPoint, int referenceChunk, int prefetchDepth, + boolean loadOnDemand, SyntheticCDORevision[] synthetics); - public void reviseVersion(CDOID id, int version, long timeStamp); + public List<CDORevision> getRevisions(List<CDOID> ids, CDOBranchPoint branchPoint, int referenceChunk, + int prefetchDepth, boolean loadOnDemand, SyntheticCDORevision[] synthetics); /** * @author Eike Stepper + * @since 3.0 */ public interface RevisionLoader { - public InternalCDORevision verifyRevision(InternalCDORevision revision, int referenceChunk); - - public InternalCDORevision loadRevision(CDOID id, int referenceChunk, int prefetchDepth); - - public InternalCDORevision loadRevisionByTime(CDOID id, int referenceChunk, int prefetchDepth, long timeStamp); - - public InternalCDORevision loadRevisionByVersion(CDOID id, int referenceChunk, int prefetchDepth, int version); - - public List<InternalCDORevision> loadRevisions(Collection<CDOID> ids, int referenceChunk, int prefetchDepth); + public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint, + int referenceChunk, int prefetchDepth); - public List<InternalCDORevision> loadRevisionsByTime(Collection<CDOID> ids, int referenceChunk, int prefetchDepth, - long timeStamp); + public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk); } /** * @author Eike Stepper + * @since 3.0 */ public interface RevisionLocker { diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/PointerCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/PointerCDORevision.java new file mode 100644 index 0000000000..4d803fe87f --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/PointerCDORevision.java @@ -0,0 +1,71 @@ +package org.eclipse.emf.cdo.spi.common.revision; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; + +import java.text.MessageFormat; + +/** + * A {@link SyntheticCDORevision synthetic} revision that represents the initial period of an object in a + * {@link CDOBranch branch} when the object is still associated with a revision from one of the baseline branches. It + * always has {@link #getVersion() version} {@link CDOBranchVersion#UNSPECIFIED_VERSION zero} and can only appear in + * branches below the {@link CDOBranch#isMainBranch() main} branch. + * + * @author Eike Stepper + * @since 3.0 + */ +public class PointerCDORevision extends SyntheticCDORevision +{ + private long revised = UNSPECIFIED_DATE; + + private CDOBranchVersion target; + + public PointerCDORevision(CDOID id, CDOBranch branch, long revised, CDOBranchVersion target) + { + super(id, branch); + this.revised = revised; + this.target = target; + } + + @Override + public final int getVersion() + { + return UNSPECIFIED_VERSION; + } + + @Override + public long getTimeStamp() + { + return getBranch().getBase().getTimeStamp(); + } + + @Override + public long getRevised() + { + return revised; + } + + @Override + public void setRevised(long revised) + { + this.revised = revised; + } + + public CDOBranchVersion getTarget() + { + return target; + } + + @Override + public String toString() + { + if (target == null) + { + return MessageFormat.format("PointerCDORevision[{0}:{1}v0 --> null]", getID(), getBranch().getID()); + } + + return MessageFormat.format("PointerCDORevision[{0}:{1}v0 --> {2}v{3}]", getID(), getBranch().getID(), target + .getBranch().getID(), target.getVersion()); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/RevisionInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/RevisionInfo.java new file mode 100644 index 0000000000..3fd408ac45 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/RevisionInfo.java @@ -0,0 +1,539 @@ +/** + * Copyright (c) 2004 - 2009 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.spi.common.revision; + +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.io.CDODataInput; +import org.eclipse.emf.cdo.common.io.CDODataOutput; +import org.eclipse.emf.cdo.common.revision.CDORevision; + +import org.eclipse.net4j.util.CheckUtil; + +import java.io.IOException; +import java.util.List; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public abstract class RevisionInfo +{ + private static final int NO_RESULT = 0; + + private static final int POINTER_RESULT = 1; + + private static final int DETACHED_RESULT = 2; + + private static final int NORMAL_RESULT = 3; + + private CDOID id; + + private CDOBranchPoint requestedBranchPoint; + + private InternalCDORevision result; + + private SyntheticCDORevision synthetic; + + protected RevisionInfo(CDOID id, CDOBranchPoint requestedBranchPoint) + { + CheckUtil.checkArg(requestedBranchPoint, "requestedBranchPoint"); + this.id = id; + this.requestedBranchPoint = requestedBranchPoint; + } + + protected RevisionInfo(CDODataInput in, CDOBranchPoint requestedBranchPoint) throws IOException + { + CheckUtil.checkArg(requestedBranchPoint, "requestedBranchPoint"); + id = in.readCDOID(); + this.requestedBranchPoint = requestedBranchPoint; + } + + public abstract Type getType(); + + public final CDOID getID() + { + return id; + } + + public final CDOBranchPoint getRequestedBranchPoint() + { + return requestedBranchPoint; + } + + public InternalCDORevision getResult() + { + return result; + } + + public void setResult(InternalCDORevision result) + { + this.result = result; + } + + public SyntheticCDORevision getSynthetic() + { + return synthetic; + } + + public void setSynthetic(SyntheticCDORevision synthetic) + { + this.synthetic = synthetic; + } + + public abstract boolean isLoadNeeded(); + + public void write(CDODataOutput out) throws IOException + { + out.writeByte(getType().ordinal()); + out.writeCDOID(getID()); + } + + public static RevisionInfo read(CDODataInput in, CDOBranchPoint requestedBranchPoint) throws IOException + { + byte ordinal = in.readByte(); + Type type = Type.values()[ordinal]; + switch (type) + { + case AVAILABLE_NORMAL: + return new Available.Normal(in, requestedBranchPoint); + + case AVAILABLE_POINTER: + return new Available.Pointer(in, requestedBranchPoint); + + case AVAILABLE_DETACHED: + return new Available.Detached(in, requestedBranchPoint); + + case MISSING: + return new Missing(in, requestedBranchPoint); + + default: + throw new IOException("Invalid revision info type: " + type); + } + } + + public void execute(InternalCDORevisionManager revisionManager, int referenceChunk) + { + SyntheticCDORevision[] synthetics = new SyntheticCDORevision[1]; + result = (InternalCDORevision)revisionManager.getRevision(getID(), requestedBranchPoint, referenceChunk, + CDORevision.DEPTH_NONE, true, synthetics); + synthetic = synthetics[0]; + } + + public void writeResult(CDODataOutput out, int referenceChunk) throws IOException + { + writeRevision(out, referenceChunk); + doWriteResult(out, synthetic, referenceChunk); + } + + public void readResult(CDODataInput in) throws IOException + { + readRevision(in); + synthetic = (SyntheticCDORevision)doReadResult(in); + } + + public void processResult(InternalCDORevisionManager revisionManager, List<CDORevision> results, + SyntheticCDORevision[] synthetics, int i) + { + if (result instanceof DetachedCDORevision) + { + results.add(null); + } + else + { + results.add(result); + } + + if (result != null) + { + revisionManager.addRevision(result); + } + + if (synthetic != null) + { + revisionManager.addRevision(synthetic); + if (synthetic instanceof PointerCDORevision) + { + PointerCDORevision pointer = (PointerCDORevision)synthetic; + CDOBranchVersion target = pointer.getTarget(); + if (target != result && target instanceof InternalCDORevision) + { + revisionManager.addRevision((CDORevision)target); + } + } + + if (synthetics != null) + { + synthetics[i] = synthetic; + } + } + } + + protected void writeRevision(CDODataOutput out, int referenceChunk) throws IOException + { + out.writeCDORevision(result, referenceChunk); + } + + protected void readRevision(CDODataInput in) throws IOException + { + result = (InternalCDORevision)in.readCDORevision(); + } + + protected void doWriteResult(CDODataOutput out, InternalCDORevision revision, int referenceChunk) throws IOException + { + if (revision == null) + { + out.writeByte(NO_RESULT); + } + else if (revision instanceof PointerCDORevision) + { + PointerCDORevision pointer = (PointerCDORevision)revision; + out.writeByte(POINTER_RESULT); + out.writeLong(pointer.getRevised()); + + CDOBranchVersion target = pointer.getTarget(); + if (target instanceof InternalCDORevision) + { + doWriteResult(out, (InternalCDORevision)target, referenceChunk); + } + else + { + out.writeByte(NO_RESULT); + } + } + else if (revision instanceof DetachedCDORevision) + { + DetachedCDORevision detached = (DetachedCDORevision)revision; + out.writeByte(DETACHED_RESULT); + out.writeLong(detached.getTimeStamp()); + out.writeInt(detached.getVersion()); + } + else + { + out.writeByte(NORMAL_RESULT); + out.writeCDORevision(revision, referenceChunk); + } + } + + protected InternalCDORevision doReadResult(CDODataInput in) throws IOException + { + byte type = in.readByte(); + switch (type) + { + case NO_RESULT: + return null; + + case POINTER_RESULT: + { + long revised = in.readLong(); + InternalCDORevision target = doReadResult(in); + return new PointerCDORevision(id, requestedBranchPoint.getBranch(), revised, target); + } + + case DETACHED_RESULT: + { + long timeStamp = in.readLong(); + int version = in.readInt(); + return new DetachedCDORevision(id, requestedBranchPoint.getBranch(), version, timeStamp); + } + + case NORMAL_RESULT: + return (InternalCDORevision)in.readCDORevision(); + + default: + throw new IllegalStateException("Invalid synthetic type: " + type); + } + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static enum Type + { + AVAILABLE_NORMAL, AVAILABLE_POINTER, AVAILABLE_DETACHED, MISSING + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static abstract class Available extends RevisionInfo + { + private CDOBranchVersion availableBranchVersion; + + protected Available(CDOID id, CDOBranchPoint requestedBranchPoint, CDOBranchVersion availableBranchVersion) + { + super(id, requestedBranchPoint); + this.availableBranchVersion = availableBranchVersion; + } + + protected Available(CDODataInput in, CDOBranchPoint requestedBranchPoint) throws IOException + { + super(in, requestedBranchPoint); + availableBranchVersion = in.readCDOBranchVersion(); + } + + public CDOBranchVersion getAvailableBranchVersion() + { + return availableBranchVersion; + } + + public boolean isDirect() + { + return availableBranchVersion.getBranch() == getRequestedBranchPoint().getBranch(); + } + + @Override + public boolean isLoadNeeded() + { + return !isDirect(); + } + + @Override + public void write(CDODataOutput out) throws IOException + { + super.write(out); + out.writeCDOBranchVersion(availableBranchVersion); + } + + @Override + protected void writeRevision(CDODataOutput out, int referenceChunk) throws IOException + { + InternalCDORevision result = getResult(); + if (result != null && result.getBranch() == availableBranchVersion.getBranch()) + { + // Use available + out.writeBoolean(true); + } + else + { + out.writeBoolean(false); + super.writeRevision(out, referenceChunk); + } + } + + @Override + protected void readRevision(CDODataInput in) throws IOException + { + boolean useAvailable = in.readBoolean(); + if (useAvailable) + { + setResult((InternalCDORevision)availableBranchVersion); + } + else + { + super.readRevision(in); + } + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static class Normal extends Available + { + public Normal(CDOID id, CDOBranchPoint requestedBranchPoint, CDOBranchVersion availableBranchVersion) + { + super(id, requestedBranchPoint, availableBranchVersion); + } + + private Normal(CDODataInput in, CDOBranchPoint requestedBranchPoint) throws IOException + { + super(in, requestedBranchPoint); + } + + @Override + public Type getType() + { + return Type.AVAILABLE_NORMAL; + } + + @Override + public InternalCDORevision getResult() + { + if (isDirect()) + { + return (InternalCDORevision)getAvailableBranchVersion(); + } + + return super.getResult(); + } + + @Override + public void processResult(InternalCDORevisionManager revisionManager, List<CDORevision> results, + SyntheticCDORevision[] synthetics, int i) + { + if (!isLoadNeeded()) + { + setResult((InternalCDORevision)getAvailableBranchVersion()); + } + + super.processResult(revisionManager, results, synthetics, i); + } + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static class Pointer extends Available + { + private CDOBranchVersion targetBranchVersion; + + private boolean hasTarget; + + public Pointer(CDOID id, CDOBranchPoint requestedBranchPoint, CDOBranchVersion availableBranchVersion, + CDOBranchVersion targetBranchVersion) + { + super(id, requestedBranchPoint, availableBranchVersion); + this.targetBranchVersion = targetBranchVersion; + hasTarget = targetBranchVersion instanceof InternalCDORevision; + } + + private Pointer(CDODataInput in, CDOBranchPoint requestedBranchPoint) throws IOException + { + super(in, requestedBranchPoint); + if (in.readBoolean()) + { + targetBranchVersion = in.readCDOBranchVersion(); + hasTarget = in.readBoolean(); + } + } + + public CDOBranchVersion getTargetBranchVersion() + { + return targetBranchVersion; + } + + @Override + public Type getType() + { + return Type.AVAILABLE_POINTER; + } + + public boolean hasTarget() + { + return hasTarget; + } + + @Override + public boolean isLoadNeeded() + { + if (getRequestedBranchPoint().getBranch().isMainBranch()) + { + return false; + } + + return !isDirect() || !hasTarget(); + } + + @Override + public void write(CDODataOutput out) throws IOException + { + super.write(out); + if (targetBranchVersion != null) + { + out.writeBoolean(true); + out.writeCDOBranchVersion(targetBranchVersion); + out.writeBoolean(hasTarget); + } + else + { + out.writeBoolean(false); + } + } + + @Override + public void processResult(InternalCDORevisionManager revisionManager, List<CDORevision> results, + SyntheticCDORevision[] synthetics, int i) + { + if (!isLoadNeeded()) + { + CDOBranchVersion target = getTargetBranchVersion(); + if (target instanceof InternalCDORevision) + { + setResult((InternalCDORevision)target); + } + + setSynthetic((PointerCDORevision)getAvailableBranchVersion()); + } + + super.processResult(revisionManager, results, synthetics, i); + } + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static class Detached extends Available + { + public Detached(CDOID id, CDOBranchPoint requestedBranchPoint, CDOBranchVersion availableBranchVersion) + { + super(id, requestedBranchPoint, availableBranchVersion); + } + + private Detached(CDODataInput in, CDOBranchPoint requestedBranchPoint) throws IOException + { + super(in, requestedBranchPoint); + } + + @Override + public Type getType() + { + return Type.AVAILABLE_DETACHED; + } + + @Override + public void processResult(InternalCDORevisionManager revisionManager, List<CDORevision> results, + SyntheticCDORevision[] synthetics, int i) + { + if (!isLoadNeeded()) + { + setSynthetic((DetachedCDORevision)getAvailableBranchVersion()); + } + + super.processResult(revisionManager, results, synthetics, i); + } + } + } + + /** + * @author Eike Stepper + * @since 3.0 + */ + public static class Missing extends RevisionInfo + { + public Missing(CDOID id, CDOBranchPoint requestedBranchPoint) + { + super(id, requestedBranchPoint); + } + + private Missing(CDODataInput in, CDOBranchPoint requestedBranchPoint) throws IOException + { + super(in, requestedBranchPoint); + } + + @Override + public Type getType() + { + return Type.MISSING; + } + + @Override + public boolean isLoadNeeded() + { + return true; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java new file mode 100644 index 0000000000..04890cd89e --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/StubCDORevision.java @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2004 - 2009 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.spi.common.revision; + +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.common.id.CDOIDProvider; +import org.eclipse.emf.cdo.common.io.CDODataInput; +import org.eclipse.emf.cdo.common.io.CDODataOutput; +import org.eclipse.emf.cdo.common.model.CDOClassInfo; +import org.eclipse.emf.cdo.common.revision.CDOList; +import org.eclipse.emf.cdo.common.revision.CDOReferenceAdjuster; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; + +import org.eclipse.emf.ecore.EStructuralFeature; + +import java.io.IOException; + +/** + * @author Eike Stepper + * @since 3.0 + */ +public class StubCDORevision extends AbstractCDORevision +{ + public StubCDORevision() + { + } + + public int compareTo(CDOBranchPoint o) + { + throw new UnsupportedOperationException(); + } + + public CDOClassInfo getClassInfo() + { + throw new UnsupportedOperationException(); + } + + public void setID(CDOID id) + { + throw new UnsupportedOperationException(); + } + + public void setVersion(int version) + { + throw new UnsupportedOperationException(); + } + + public void setBranchPoint(CDOBranchPoint branchPoint) + { + throw new UnsupportedOperationException(); + } + + public void setRevised(long revised) + { + throw new UnsupportedOperationException(); + } + + public void setResourceID(CDOID resourceID) + { + throw new UnsupportedOperationException(); + } + + public void setContainerID(Object containerID) + { + throw new UnsupportedOperationException(); + } + + public void setContainingFeatureID(int containingFeatureID) + { + throw new UnsupportedOperationException(); + } + + public void add(EStructuralFeature feature, int index, Object value) + { + throw new UnsupportedOperationException(); + } + + public void clear(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex) + { + throw new UnsupportedOperationException(); + } + + public Object remove(EStructuralFeature feature, int index) + { + throw new UnsupportedOperationException(); + } + + public Object set(EStructuralFeature feature, int index, Object value) + { + throw new UnsupportedOperationException(); + } + + public void unset(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public Object getValue(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public Object setValue(EStructuralFeature feature, Object value) + { + throw new UnsupportedOperationException(); + } + + public void setList(EStructuralFeature feature, InternalCDOList list) + { + throw new UnsupportedOperationException(); + } + + public CDOList getList(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public CDOList getList(EStructuralFeature feature, int size) + { + throw new UnsupportedOperationException(); + } + + public void read(CDODataInput in) throws IOException + { + throw new UnsupportedOperationException(); + } + + public void write(CDODataOutput out, int referenceChunk) throws IOException + { + throw new UnsupportedOperationException(); + } + + public void convertEObjects(CDOIDProvider oidProvider) + { + throw new UnsupportedOperationException(); + } + + public int getVersion() + { + throw new UnsupportedOperationException(); + } + + public long getRevised() + { + throw new UnsupportedOperationException(); + } + + public CDORevisionDelta compare(CDORevision origin) + { + throw new UnsupportedOperationException(); + } + + public void merge(CDORevisionDelta delta) + { + throw new UnsupportedOperationException(); + } + + public CDORevision copy() + { + throw new UnsupportedOperationException(); + } + + public CDOID getID() + { + throw new UnsupportedOperationException(); + } + + public CDOBranch getBranch() + { + throw new UnsupportedOperationException(); + } + + public long getTimeStamp() + { + throw new UnsupportedOperationException(); + } + + public CDOID getResourceID() + { + throw new UnsupportedOperationException(); + } + + public Object getContainerID() + { + throw new UnsupportedOperationException(); + } + + public int getContainingFeatureID() + { + throw new UnsupportedOperationException(); + } + + public Object get(EStructuralFeature feature, int index) + { + throw new UnsupportedOperationException(); + } + + public int size(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public boolean isEmpty(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public boolean contains(EStructuralFeature feature, Object value) + { + throw new UnsupportedOperationException(); + } + + public int indexOf(EStructuralFeature feature, Object value) + { + throw new UnsupportedOperationException(); + } + + public int lastIndexOf(EStructuralFeature feature, Object value) + { + throw new UnsupportedOperationException(); + } + + public <T> T[] toArray(EStructuralFeature feature, T[] array) + { + throw new UnsupportedOperationException(); + } + + public Object[] toArray(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public int hashCode(EStructuralFeature feature) + { + throw new UnsupportedOperationException(); + } + + public void adjustReferences(CDOReferenceAdjuster revisionAdjuster) + { + throw new UnsupportedOperationException(); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/SyntheticCDORevision.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/SyntheticCDORevision.java new file mode 100644 index 0000000000..8150ae77df --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/revision/SyntheticCDORevision.java @@ -0,0 +1,51 @@ +package org.eclipse.emf.cdo.spi.common.revision; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevisionManager; +import org.eclipse.emf.cdo.common.revision.cache.CDORevisionCache; + +/** + * A synthetic revision that represents the initial period of an object in a {@link CDOBranch branch} when the object is + * still associated with a revision from one of the baseline branches. It always has {@link #getVersion() version} + * {@link CDOBranchVersion#UNSPECIFIED_VERSION zero} and can only appear in branches below the + * {@link CDOBranch#isMainBranch() main} branch. + * <p> + * Synthetic revisions are used for two slightly different purposes: + * <ol> + * <li>For {@link CDORevisionCache cache} optimization. + * <li>As a persistent "detach marker" indicating that the first modification of an object in a branch is its deletion. + * </ol> + * <p> + * Instances of this marker revision are not supposed to be exposed outside of a revision {@link CDORevisionManager + * manager}. They are mainly used in the communication between a revision manager and its associated revision + * {@link InternalCDORevisionManager.RevisionLoader loader}. + * + * @author Eike Stepper + * @since 3.0 + */ +public abstract class SyntheticCDORevision extends StubCDORevision +{ + private CDOID id; + + private CDOBranch branch; + + public SyntheticCDORevision(CDOID id, CDOBranch branch) + { + this.id = id; + this.branch = branch; + } + + @Override + public CDOID getID() + { + return id; + } + + @Override + public CDOBranch getBranch() + { + return branch; + } +} |