diff options
author | Victor Roldan Betancort | 2013-08-09 12:55:41 +0000 |
---|---|---|
committer | Victor Roldan Betancort | 2013-08-09 12:55:41 +0000 |
commit | ceaa9cd5f320abae7c109852ac1d9a01f1e7cf37 (patch) | |
tree | c3b6b2f18228c6d58c4617f81f6c8949599b4519 | |
parent | 02defe32410e41b300dac05f8835bb4307645c10 (diff) | |
download | cdo-committers/vroldanbet/couchbase.tar.gz cdo-committers/vroldanbet/couchbase.tar.xz cdo-committers/vroldanbet/couchbase.zip |
[414770] Implement Couchbase based IStore committers/vroldanbet/couchbase
https://bugs.eclipse.org/bugs/show_bug.cgi?id=414770
43 files changed, 4115 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/.classpath b/plugins/org.eclipse.emf.cdo.server.couchbase/.classpath new file mode 100644 index 0000000000..64c5e31b7a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/.project b/plugins/org.eclipse.emf.cdo.server.couchbase/.project new file mode 100644 index 0000000000..b89e96a62a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.emf.cdo.server.couchbase</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.emf.cdo.server.couchbase/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..af0f20f97a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.couchbase/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..fdece13338 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/META-INF/MANIFEST.MF @@ -0,0 +1,14 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Couchbase CDO Server +Bundle-SymbolicName: org.eclipse.emf.cdo.server.couchbase +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: eclipse.org +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Require-Bundle: com.google.gson;bundle-version="[2.2.0,3.0.0)", + org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)", + com.couchbase.client;bundle-version="[1.1.5,2.0.0)", + net.spy.memcached;bundle-version="[2.8.0,3.0.0)" +Export-Package: org.eclipse.emf.cdo.server.couchbase;version="1.0.0", + org.eclipse.emf.cdo.server.internal;version="1.0.0";x-friends:="org.eclipse.emf.cdo.tests.couchbase", + org.eclipse.emf.cdo.server.internal.couchbase.bundle;version="1.0.0";x-internal:=true diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/build.properties b/plugins/org.eclipse.emf.cdo.server.couchbase/build.properties new file mode 100644 index 0000000000..34d2e4d2da --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/couchbase/ICouchbaseStore.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/couchbase/ICouchbaseStore.java new file mode 100644 index 0000000000..3e80bee6ed --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/couchbase/ICouchbaseStore.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2013 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: + * Victor Roldan Betancort - initial API and implementation + */ + +package org.eclipse.emf.cdo.server.couchbase; + +import org.eclipse.emf.cdo.server.IStore; + +/** + * The main entry point to the API of CDO's integration with Couchbase database. + * + * @author Victor Roldan Betancort + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICouchbaseStore extends IStore +{ + public static final String TYPE = "couchbase"; +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/couchbase/package-info.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/couchbase/package-info.java new file mode 100644 index 0000000000..8ab5557942 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/couchbase/package-info.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2011-2013 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: + * Victor Roldan Betancort - initial API and implementation + */ + +/** + * Server concepts for dealing with Couchbase stores and accessors. + */ +package org.eclipse.emf.cdo.server.couchbase; + diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStore.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStore.java new file mode 100644 index 0000000000..8dcf63869c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStore.java @@ -0,0 +1,165 @@ +package org.eclipse.emf.cdo.server.internal; + +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.eclipse.emf.cdo.server.ISession; +import org.eclipse.emf.cdo.server.IStoreAccessor; +import org.eclipse.emf.cdo.server.ITransaction; +import org.eclipse.emf.cdo.server.IView; +import org.eclipse.emf.cdo.server.couchbase.ICouchbaseStore; +import org.eclipse.emf.cdo.server.internal.commitables.StoreMetaHandler; +import org.eclipse.emf.cdo.server.internal.couchbase.bundle.OM; +import org.eclipse.emf.cdo.spi.server.LongIDStore; +import org.eclipse.emf.cdo.spi.server.StoreAccessorBase; +import org.eclipse.emf.cdo.spi.server.StoreAccessorPool; +import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; +import org.eclipse.net4j.util.lifecycle.LifecycleUtil; + +import com.couchbase.client.CouchbaseClient; +import com.couchbase.client.CouchbaseConnectionFactory; +import com.couchbase.client.CouchbaseConnectionFactoryBuilder; + +public class CouchbaseStore extends LongIDStore implements ICouchbaseStore { + + private static final int COUCHBASE_OPERATION_TIMEOUT = 10000; + + private List<URI> clusterList; + + private String bucketName; + + private CouchbaseClient client; + + @ExcludeFromDump + private transient final StoreAccessorPool readerPool = new StoreAccessorPool( + this, null); + + @ExcludeFromDump + private transient final StoreAccessorPool writerPool = new StoreAccessorPool( + this, null); + + @ExcludeFromDump + private String password; + + @ExcludeFromDump + private String user; + + private StoreMetaHandler storeMetaHandler; + + public CouchbaseStore(List<URI> clusterList, String bucketName, String user, String password) { + super(ICouchbaseStore.TYPE, set(ChangeFormat.REVISION), set( + RevisionTemporality.NONE, RevisionTemporality.AUDITING), set( + RevisionParallelism.NONE, RevisionParallelism.BRANCHING)); + + this.clusterList = clusterList; + this.bucketName = bucketName; + this.user = user; + this.password = password; + } + + public StoreMetaHandler getStoreMetaHandler() { + if (storeMetaHandler == null) { + storeMetaHandler = new StoreMetaHandler(getClient()); + } + return storeMetaHandler; + } + + public CouchbaseClient openClient() { + try { + CouchbaseConnectionFactoryBuilder connectionFactoryBuilder = new CouchbaseConnectionFactoryBuilder(); + // Reduces the rate of random "Cancelled" upon client.get() calls; still happens though + connectionFactoryBuilder.setOpTimeout(COUCHBASE_OPERATION_TIMEOUT); + CouchbaseConnectionFactory connectionFactory = connectionFactoryBuilder.buildCouchbaseConnection(clusterList, bucketName, user, password); + return new CouchbaseClient((CouchbaseConnectionFactory)connectionFactory); + } catch (IOException e) { + OM.LOG.error(e); + } + return null; + } + + private CouchbaseClient getClient() { + if (client == null) { + client = openClient(); + } + return client; + } + + @Override + protected void doActivate() throws Exception { + super.doActivate(); + Long lastCDOID = getStoreMetaHandler().getLastCDOID(); + if (lastCDOID != null) { + setLastObjectID(lastCDOID); + } + setLastCommitTime(storeMetaHandler.getLastCommitTime()); + } + + @Override + protected void doDeactivate() throws Exception { + super.doDeactivate(); + storeMetaHandler.setIsFirstStart(false); + storeMetaHandler.setLastCommitTime(getLastCommitTime()); + if (client != null) { + client.shutdown(10, TimeUnit.SECONDS); // Its important to gracefully shutdown, or we may lost data recently committed + client = null; + } + StoreAccessorBase readerAccessor; + while ((readerAccessor = readerPool.removeStoreAccessor(this)) != null) { + LifecycleUtil.deactivate(readerAccessor); + } + StoreAccessorBase writerAccessor; + while ((writerAccessor = writerPool.removeStoreAccessor(this)) != null) { + LifecycleUtil.deactivate(writerAccessor); + } + + } + + public void setCreationTime(long creationTime) { + storeMetaHandler.setCreationTime(creationTime); + } + + public boolean isFirstStart() { + return storeMetaHandler.isFirstStart(); + } + + public long getCreationTime() { + return storeMetaHandler.getCreationTime(); + } + + public Map<String, String> getPersistentProperties(Set<String> names) { + return storeMetaHandler.getPersistentProperties(names); + } + + public void setPersistentProperties(Map<String, String> properties) { + storeMetaHandler.setPersistentProperties(properties); + } + + public void removePersistentProperties(Set<String> names) { + storeMetaHandler.removePersistentProperties(names); + } + + @Override + protected StoreAccessorPool getReaderPool(ISession session, boolean forReleasing) { + return readerPool; + } + + @Override + protected StoreAccessorPool getWriterPool(IView view, boolean forReleasing) { + return writerPool; + } + + @Override + protected IStoreAccessor createReader(ISession session) { + return new CouchbaseStoreAccessor(this, session); + } + + @Override + protected IStoreAccessor createWriter(ITransaction transaction) { + return new CouchbaseStoreAccessor(this, transaction); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStoreAccessor.java new file mode 100644 index 0000000000..f22df27ebe --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStoreAccessor.java @@ -0,0 +1,353 @@ +package org.eclipse.emf.cdo.server.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchHandler; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.lob.CDOLobHandler; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler; +import org.eclipse.emf.cdo.common.protocol.CDODataInput; +import org.eclipse.emf.cdo.common.protocol.CDODataOutput; +import org.eclipse.emf.cdo.common.revision.CDORevisionCacheAdder; +import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; +import org.eclipse.emf.cdo.common.util.CDOQueryInfo; +import org.eclipse.emf.cdo.server.IQueryHandler; +import org.eclipse.emf.cdo.server.ISession; +import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking; +import org.eclipse.emf.cdo.server.IStoreAccessor.Raw; +import org.eclipse.emf.cdo.server.IStoreChunkReader; +import org.eclipse.emf.cdo.server.ITransaction; +import org.eclipse.emf.cdo.server.internal.commitables.CommitInfoHandler; +import org.eclipse.emf.cdo.server.internal.commitables.ICommitable; +import org.eclipse.emf.cdo.server.internal.commitables.LobHandler; +import org.eclipse.emf.cdo.server.internal.commitables.LockingHandler; +import org.eclipse.emf.cdo.server.internal.commitables.PackageUnitHandler; +import org.eclipse.emf.cdo.server.internal.commitables.ResourceHandler; +import org.eclipse.emf.cdo.server.internal.commitables.RevisionHandler; +import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment; +import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; +import org.eclipse.emf.cdo.spi.server.LongIDStoreAccessor; +import org.eclipse.emf.cdo.spi.server.Store; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.net4j.util.collection.Pair; +import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class CouchbaseStoreAccessor extends LongIDStoreAccessor implements Raw, + DurableLocking { + + private List<ICommitable> transaction = new ArrayList<ICommitable>(); + + private CouchbaseClient client; + + private RevisionHandler revisionHandler; + + private ResourceHandler resourceHandler; + + private PackageUnitHandler packageUnitHandler; + + private CommitInfoHandler commitInfoHandler; + + private LobHandler lobHandler; + + private LockingHandler lockingHandler; + + protected CouchbaseStoreAccessor(Store store, ISession session) { + super(store, session); + } + + public CouchbaseStoreAccessor(Store store, ITransaction transaction) { + super(store, transaction); + } + + private void initHandlers() { + revisionHandler = new RevisionHandler(getClient(), getStore()); + resourceHandler = new ResourceHandler(getClient(), getStore()); + packageUnitHandler = new PackageUnitHandler(getClient(), getStore()); + commitInfoHandler = new CommitInfoHandler(getClient(), getStore()); + lobHandler = new LobHandler(getClient(), getStore()); + lockingHandler = new LockingHandler(getClient(), getStore()); + } + + @Override + public CouchbaseStore getStore() { + return (CouchbaseStore) super.getStore(); + } + + @Override + protected void doActivate() throws Exception { + super.doActivate(); + if (client == null) { + client = getStore().openClient(); + } + initHandlers(); + } + + @Override + protected void doDeactivate() throws Exception { + super.doDeactivate(); + if (getClient() != null) { + getClient().shutdown(10, TimeUnit.SECONDS); + } + } + + private CouchbaseClient getClient() { + return client; + } + + public IStoreChunkReader createChunkReader(InternalCDORevision revision, EStructuralFeature feature) { + throw new UnsupportedOperationException("not implemented"); + } + + public Collection<InternalCDOPackageUnit> readPackageUnits() { + return packageUnitHandler.readPackageUnits(); + } + + public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit) { + return packageUnitHandler.loadPackageUnit(packageUnit); + } + + public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint, int listChunk, CDORevisionCacheAdder cache) { + return revisionHandler.readRevision(id, branchPoint); + } + + public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk, CDORevisionCacheAdder cache) { + throw new UnsupportedOperationException("not implemented"); + } + + public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime, CDORevisionHandler handler) { + revisionHandler.handleRevisions(eClass, branch, timeStamp, exactTime, handler); + } + + public Set<CDOID> readChangeSet(OMMonitor monitor, CDOChangeSetSegment... segments) { + throw new UnsupportedOperationException("not implemented"); + } + + public void queryResources(QueryResourcesContext context) { + resourceHandler.queryResources(context); + } + + public void queryXRefs(QueryXRefsContext context) { + revisionHandler.queryXRefs(context); + } + + public void queryLobs(List<byte[]> ids) { + for (Iterator<byte[]> it = ids.iterator(); it.hasNext();) + { + if (lobHandler.readLob(it.next()) == null) + { + it.remove(); + } + } + } + + public void loadLob(byte[] id, OutputStream out) throws IOException { + lobHandler.loadLob(id, out); + } + + public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException { + lobHandler.handleLobs(fromTime, toTime, handler); + } + + public void writePackageUnits(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor) { + for (InternalCDOPackageUnit packageUnit : packageUnits) { + addToTransaction(packageUnitHandler.createPackageUnitCommitable(packageUnit)); + } + } + + public IQueryHandler getQueryHandler(CDOQueryInfo info) { + return null; + } + + public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo) { + throw new UnsupportedOperationException("not implemented"); + } + + public BranchInfo loadBranch(int branchID) { + throw new UnsupportedOperationException("not implemented"); + } + + public SubBranchInfo[] loadSubBranches(int branchID) { + throw new UnsupportedOperationException("not implemented"); + } + + public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler) { + throw new UnsupportedOperationException("not implemented"); + } + + public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler) { + commitInfoHandler.loadCommitInfos(branch, startTime, endTime, handler); + } + + public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks) throws LockAreaAlreadyExistsException { + return lockingHandler.createLockArea(userID, branchPoint, readOnly, locks); + } + + public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException { + return lockingHandler.getLockArea(durableLockingID); + } + + public void getLockAreas(String userIDPrefix, Handler handler) { + lockingHandler.getLockAreas(userIDPrefix, handler); + } + + public void deleteLockArea(String durableLockingID) { + lockingHandler.deleteLockArea(durableLockingID); + } + + public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock) { + lockingHandler.lock(durableLockingID, type, objectsToLock); + } + + public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock) { + lockingHandler.unlock(durableLockingID, type, objectsToUnlock); + } + + public void unlock(String durableLockingID) { + lockingHandler.unlock(durableLockingID); + } + + public void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime) throws IOException { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime, OMMonitor monitor) throws IOException { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawStore(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor) { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawStore(InternalCDORevision revision, OMMonitor monitor) { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawStore(byte[] id, long size, InputStream inputStream) throws IOException { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawStore(byte[] id, long size, Reader reader) throws IOException { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawStore(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor) { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawDelete(CDOID id, int version, CDOBranch branch, EClass eClass, OMMonitor monitor) { + throw new UnsupportedOperationException("not implemented"); + } + + public void rawCommit(double commitWork, OMMonitor monitor) { + throw new UnsupportedOperationException("not implemented"); + } + + private void addToTransaction(ICommitable commitable) { + transaction.add(commitable); + } + + @Override + protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor) { + addToTransaction(commitInfoHandler.createWriteCommitInfoCommitable(branch, timeStamp, previousTimeStamp, userID, comment)); + } + + @Override + protected void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor) { + monitor.begin(revisions.length); + try + { + for (InternalCDORevision revision : revisions) + { + writeRevision(revision, monitor.fork()); + } + } + finally + { + monitor.done(); + } + } + + protected void writeRevision(InternalCDORevision revision, OMMonitor monitor) { + monitor.begin(10); + try + { + addToTransaction(revisionHandler.createRevisionWriteCommitable(revision)); + } finally { + monitor.done(); + } + } + + @Override + protected void writeRevisionDeltas(InternalCDORevisionDelta[] revisionDeltas, CDOBranch branch, long created, OMMonitor monitor) { + throw new UnsupportedOperationException("not implemented"); + } + + @Override + protected void detachObjects(CDOID[] detachedObjects, CDOBranch branch, long timeStamp, OMMonitor monitor) { + monitor.begin(detachedObjects.length); + + try + { + for (CDOID id : detachedObjects) + { + addToTransaction(revisionHandler.createRevisionDetachCommitable(id, branch)); + monitor.worked(); + } + } + finally + { + monitor.done(); + } + } + + @Override + protected void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException { + addToTransaction(lobHandler.createWriteBlobCommitable(id, size, inputStream)); + } + + @Override + protected void writeClob(byte[] id, long size, Reader reader) throws IOException { + addToTransaction(lobHandler.createWriteClobCommitable(id, size, reader)); + } + + @Override + protected void doCommit(OMMonitor monitor) { + monitor.begin(transaction.size()); + try { + for (ICommitable commitable : transaction) { + commitable.commit(monitor.fork()); + } + transaction.clear(); + } + finally + { + monitor.done(); + } + } + + @Override + protected void doRollback(CommitContext commitContext) { + transaction.clear(); + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStoreFactory.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStoreFactory.java new file mode 100644 index 0000000000..dcea0cb1d1 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/CouchbaseStoreFactory.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2013 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: + * Victor Roldan Betancort - initial API and implementation + */ +package org.eclipse.emf.cdo.server.internal; + +import java.net.URI; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.IStoreFactory; +import org.eclipse.emf.cdo.server.couchbase.ICouchbaseStore; +import org.eclipse.emf.cdo.spi.server.RepositoryConfigurator; +import org.w3c.dom.Element; + +public class CouchbaseStoreFactory implements IStoreFactory { + + private static final String PROPERTY_URI = "uri"; + + private static final String PROPERTY_BUCKET = "bucket"; + + private static final String PROPERTY_PASSWORD = "password"; + + private static final Object PROPERTY_USER = "user"; + + public String getStoreType() { + return ICouchbaseStore.TYPE; + } + + public IStore createStore(String repositoryName, + Map<String, String> repositoryProperties, Element storeConfig) { + Map<String, String> properties = RepositoryConfigurator.getProperties( + storeConfig, 1); + String uri = properties.get(PROPERTY_URI); + String bucket = properties.get(PROPERTY_BUCKET); + String user = properties.get(PROPERTY_USER); + String pass = properties.get(PROPERTY_PASSWORD); + List<URI> uris = new LinkedList<URI>(); + uris.add(URI.create(uri)); + return new CouchbaseStore(uris, bucket, user, pass); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/AbstractCommitable.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/AbstractCommitable.java new file mode 100644 index 0000000000..8849e3a084 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/AbstractCommitable.java @@ -0,0 +1,117 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import net.spy.memcached.CASValue; +import net.spy.memcached.internal.OperationFuture; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.server.internal.couchbase.bundle.OM; + +import com.couchbase.client.CouchbaseClient; + +public abstract class AbstractCommitable extends CouchbaseHandler implements ICommitable { + + private StoreMetaHandler storeMetaHandler; + + protected enum PersistMethod { + ADD, DELETE, SET, APPEND, APPEND_IF_NOT_CONTAINED, DELETE_APPENDED + } + + private CDOID cdoid = CDOID.NULL; + + public AbstractCommitable(CouchbaseClient client) { + super(client); + storeMetaHandler = new StoreMetaHandler(client); + } + + public CDOID getCDOID() { + return cdoid; + } + + protected void setCDOID(CDOID id) { + cdoid = id; + } + + protected void doCommit(String key, Object value, CDOID id, PersistMethod persistMethod) { + Long storedLastCDOID = storeMetaHandler.getLastCDOID(); + long lastCDOID = storedLastCDOID == null? -1 : storedLastCDOID; + boolean newLastCDOIDFound = false; + long commitableID = CDOIDUtil.getLong(id); + if (commitableID > lastCDOID) { + lastCDOID = commitableID; + newLastCDOIDFound = true; + } + // write actual data + switch (persistMethod) { + case DELETE: + getClient().delete(key); + break; + case ADD: + getClient().add(key, 0, value); + break; + case SET: + getClient().set(key, 0, value); + break; + case DELETE_APPENDED: + List<String> multivalue = getMultiValue(key); + Iterator<String> it = multivalue.iterator(); + String valueString = value.toString(); + while (it.hasNext()) { + String fetchedValue = it.next(); + if (fetchedValue.equals(valueString)) { + it.remove(); + } + } + StringBuilder builder = new StringBuilder(); + for (String fetchedValue : multivalue) { + builder.append(getSeparator() + fetchedValue); + } + if (builder.length() > 0) { + builder.deleteCharAt(0); + } + doCommit(key, builder.toString(), id, PersistMethod.SET); + break; + case APPEND_IF_NOT_CONTAINED: + List<String> valueList = getMultiValue(key); + String valueString2 = value.toString(); + for(String valueFromList : valueList) { + if (valueFromList.equals(valueString2)) { + return; + } + } + doCommit(key, value, id, PersistMethod.APPEND); + break; + case APPEND: + CASValue<Object> cas = getClient().gets(key); + if (cas == null || "".equals(cas.getValue())) { //FIXME why sometimes value is empty? + doCommit(key, value.toString(), id, PersistMethod.SET); + } else { + doAppend(key, value, cas); + } + break; + } + if (newLastCDOIDFound) { + storeMetaHandler.setLastCDOID(lastCDOID); + } + } + + private void doAppend(String key, Object value, CASValue<Object> cas) { + for(;;) { + OperationFuture<Boolean> future = getClient().append(cas.getCas(), key, getSeparator() + value.toString()); + try { + if (future.get()) { + break; + } + } catch (InterruptedException e) { + OM.LOG.error(e); + } catch (ExecutionException e) { + OM.LOG.error(e); + } + } + } + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/CommitInfoHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/CommitInfoHandler.java new file mode 100644 index 0000000000..003b11256a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/CommitInfoHandler.java @@ -0,0 +1,143 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; +import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil; +import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; +import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.net4j.util.collection.Pair; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class CommitInfoHandler extends JSONHandler { + + public CommitInfoHandler(CouchbaseClient client, IStore store) { + super(client, store); + } + + protected String getCommitInfoKey(CDOBranch branch, long timeStamp) { + return getCommitInfoKey(branch.getID(), timeStamp); + } + + protected String getCommitInfoKey(int branch, long timeStamp) { + return "CDOCommitInfo::Branch-" + branch + "::TimeStamp-" + timeStamp; + } + + protected String getCommitInfoListKey() { + return "CDOCommitInfo"; + } + + public ICommitable createWriteCommitInfoCommitable(final CDOBranch branch, final long timeStamp, + final long previousTimeStamp, final String userID, final String comment) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + JSONCommitInfo info = new JSONCommitInfo(branch.getID(), timeStamp, previousTimeStamp, userID, comment); + doCommit(getCommitInfoKey(branch, timeStamp), toJson(info), null, PersistMethod.ADD); + String keyListValue = branch.getID() + getCommitInfoSeparator() + timeStamp; + doCommit(getCommitInfoListKey(), keyListValue, null, PersistMethod.APPEND); + } + }; + } + + protected String getCommitInfoSeparator() { + return "#"; + } + + public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler) { + List<Pair<Integer, Long>> keyPairs = getBranchAndTimestamp(); + // look for branch matches + List<Pair<Integer, Long>> matchedBranch = new ArrayList<Pair<Integer, Long>>(); + if (branch != null) { + for (Pair<Integer, Long> keyPair : keyPairs) { + if (branch.getID() == keyPair.getElement1()) { + matchedBranch.add(keyPair); + } + } + } else { + // branch is not defined, we consider all branch/timestamp combinations + matchedBranch = keyPairs; + } + + + // if not encoded in the endTime, infos should be returned + // ordered in a descending manner (from latter commits to earlier) + + // if endTime < starTime, it means the info count is coded in that parameter + // it means that we must return "endTime" commit infos + // Depending on the sign of the number (positive or negative) + // we should order in a ascending or descending, correspondingly + + long count = CDOCommitInfoUtil.decodeCount(endTime); + final boolean descendant; + if (count < CDOBranchPoint.UNSPECIFIED_DATE || endTime >= startTime) { + descendant = true; + } else { + descendant = false; + } + count = Math.abs(count); + List<Pair<Integer, Long>> matchedTimestamp = new ArrayList<Pair<Integer, Long>>(); + Collections.sort(matchedBranch, new Comparator<Pair<Integer, Long>>() { + public int compare(Pair<Integer, Long> arg0, Pair<Integer, Long> arg1) { + if (descendant) { + return arg0.getElement2() > arg1.getElement2() ? -1 : 1; + } else { + return arg0.getElement2() > arg1.getElement2() ? 1 : -1; + } + } + }); + int currentCount = 0; + for (Pair<Integer, Long> keyPair : matchedBranch) { + if (startTime != CDOBranchPoint.UNSPECIFIED_DATE && keyPair.getElement2() < startTime) + { + continue; + } + if (endTime != CDOBranchPoint.UNSPECIFIED_DATE && endTime > startTime && keyPair.getElement2() > endTime) + { + continue; + } + currentCount++; + if (currentCount > count) { + break; + } + matchedTimestamp.add(keyPair); + } + // Fetch for database actual CommitInfo instances + List<JSONCommitInfo> infos = new ArrayList<JSONCommitInfo>(); + for (Pair<Integer, Long> match : matchedTimestamp) { + String key = getCommitInfoKey(match.getElement1(), match.getElement2()); + Object obj = getValue(key); + JSONCommitInfo info = fromJson((String)obj, JSONCommitInfo.class); + infos.add(info); + } + + InternalRepository repository = (InternalRepository)getStore().getRepository(); + InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager(); + InternalCDOBranchManager branchManager = repository.getBranchManager(); + + for (JSONCommitInfo info : infos) { + info.handle(branchManager, commitInfoManager, handler); + } + + } + + private List<Pair<Integer, Long>> getBranchAndTimestamp() { + List<String> splittedKeys = getMultiValue(getCommitInfoListKey()); + List<Pair<Integer, Long>> keyPairs = new ArrayList<Pair<Integer, Long>>(); + // Parse branch and key + for (String key : splittedKeys) { + String[] branchAndTimestamp = key.split(getCommitInfoSeparator()); + keyPairs.add(new Pair<Integer, Long>(Integer.valueOf(branchAndTimestamp[0]), Long.valueOf(branchAndTimestamp[1]))); + } + return keyPairs; + } + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/CouchbaseHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/CouchbaseHandler.java new file mode 100644 index 0000000000..f2482fd700 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/CouchbaseHandler.java @@ -0,0 +1,45 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.couchbase.client.CouchbaseClient; + +public class CouchbaseHandler { + + private CouchbaseClient client; + + public CouchbaseHandler(CouchbaseClient client) { + this.client = client; + } + + protected CouchbaseClient getClient() { + return client; + } + + protected Object getValue(String key) { + return getClient().get(key); + } + + @SuppressWarnings("unchecked") + protected List<String> getMultiValue(String key) { + String keys = (String)getValue(key); + // FIXME there should not be empty values committed, investigate this + if (keys == null || "".equals(keys)) { + return Collections.EMPTY_LIST; + } + String[] splittedValues = keys.split(getSeparator()); + List<String> result = new ArrayList<String>(); + for (String value : splittedValues) { + result.add(value); + } + return result; + } + + protected String getSeparator() { + return ";"; + } + + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/ICommitable.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/ICommitable.java new file mode 100644 index 0000000000..7ae00e11d7 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/ICommitable.java @@ -0,0 +1,12 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +public interface ICommitable { + + public CDOID getCDOID(); + + public void commit(OMMonitor monitor); + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/JSONCommitInfo.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/JSONCommitInfo.java new file mode 100644 index 0000000000..dcb4af0d17 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/JSONCommitInfo.java @@ -0,0 +1,47 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler; +import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; +import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; +import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; + +public class JSONCommitInfo +{ + private int branchID; + + private long timeStamp; + + private long previousTimeStamp; + + private String userID; + + private String comment; + + public JSONCommitInfo(int branchID, long timeStamp, long previousTimeStamp, String userID, String comment) + { + this.branchID = branchID; + this.timeStamp = timeStamp; + this.previousTimeStamp = previousTimeStamp; + this.userID = userID; + this.comment = comment; + } + + public int getBranchID() + { + return branchID; + } + + public long getTimeStamp() + { + return timeStamp; + } + + public void handle(InternalCDOBranchManager branchManager, InternalCDOCommitInfoManager manager, + CDOCommitInfoHandler handler) + { + InternalCDOBranch branch = branchManager.getBranch(branchID); + CDOCommitInfo commitInfo = manager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, null); + handler.handleCommitInfo(commitInfo); + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/JSONHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/JSONHandler.java new file mode 100644 index 0000000000..4b2c57bb7a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/JSONHandler.java @@ -0,0 +1,34 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.internal.couchbase.marshall.JSONRevision; +import org.eclipse.emf.cdo.server.internal.couchbase.marshall.JSONRevisionTypeAdapter; + +import com.couchbase.client.CouchbaseClient; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public abstract class JSONHandler extends StoreHandler { + + private Gson gson; + + private void initGson() { + GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(JSONRevision.class, new JSONRevisionTypeAdapter(getStore())); + gson = builder.serializeNulls().create(); + } + + public JSONHandler(CouchbaseClient client, IStore store) { + super(client, store); + initGson(); + } + + protected <TYPE> TYPE fromJson(String jsonString, Class<TYPE> clazz) { + return gson.fromJson(jsonString, clazz); + } + + protected String toJson(Object elemenToJson) { + return gson.toJson(elemenToJson); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/LobHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/LobHandler.java new file mode 100644 index 0000000000..9cc0008499 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/LobHandler.java @@ -0,0 +1,148 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; + +import org.eclipse.emf.cdo.common.lob.CDOLobHandler; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.net4j.util.HexUtil; +import org.eclipse.net4j.util.io.IOUtil; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class LobHandler extends StoreHandler { + + public LobHandler(CouchbaseClient client, IStore store) { + super(client, store); + } + + public Object readLob(byte[] id) { + Object result = getValue(getBlobKey(id)); + if (result == null) { + return getValue(getClobKey(id)); + } + return result; + } + + public void loadLob(byte[] id, OutputStream out) { + Object rawObject = getValue(getBlobKey(id)); + if (rawObject != null) { + byte[] byteArray = (byte[])rawObject; + ByteArrayInputStream in = new ByteArrayInputStream(byteArray); + try { + IOUtil.copyBinary(in, out, byteArray.length); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + rawObject = getValue(getClobKey(id)); + char[] charArray = (char[])rawObject; + CharArrayReader in = new CharArrayReader(charArray); + try { + IOUtil.copyCharacter(in, new OutputStreamWriter(out), charArray.length); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + } + + public ICommitable createWriteBlobCommitable(final byte[] id, final long size, final InputStream inputStream) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + IOUtil.copyBinary(inputStream, out, size); + } catch (IOException e) { + throw new RuntimeException(e); + } + doCommit(getBlobKey(id), out.toByteArray(), null, PersistMethod.ADD); + doCommit("LOB", HexUtil.bytesToHex(id), null, PersistMethod.APPEND); + } + }; + } + + public ICommitable createWriteClobCommitable(final byte[] id, final long size, final Reader reader) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + CharArrayWriter out = new CharArrayWriter(); + try { + IOUtil.copyCharacter(reader, out, size); + } catch (IOException e) { + throw new RuntimeException(e); + } + doCommit(getClobKey(id), out.toCharArray(), null, PersistMethod.ADD); + doCommit(getAllLobKey(), HexUtil.bytesToHex(id), null, PersistMethod.APPEND); + } + }; + } + + public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException { + for (String id : getMultiValue(getAllLobKey())) { + Object rawBlob = getValue(getBlobKey(id)); + if (rawBlob != null) { + byte[] byteArray = (byte[])rawBlob; + ByteArrayInputStream in = new ByteArrayInputStream(byteArray); + OutputStream out = handler.handleBlob(HexUtil.hexToBytes(id), byteArray.length); + if (out != null) + { + try + { + IOUtil.copyBinary(in, out, byteArray.length); + } + finally + { + IOUtil.close(out); + } + } + } else { + Object rawClob = getValue(getClobKey(id)); + if (rawClob != null) { + char[] clob = (char[])rawClob; + CharArrayReader in = new CharArrayReader(clob); + Writer out = handler.handleClob(HexUtil.hexToBytes(id), clob.length); + if (out != null) + { + try + { + IOUtil.copyCharacter(in, out, clob.length); + } + finally + { + IOUtil.close(out); + } + } + } + } + } + } + + protected String getBlobKey(byte[] id) { + return getBlobKey(HexUtil.bytesToHex(id)); + } + + protected String getBlobKey(String id) { + return "BLOB::" + id; + } + + protected String getClobKey(byte[] id) { + return getClobKey(HexUtil.bytesToHex(id)); + } + + protected String getClobKey(String id) { + return "CLOB::" + id; + } + + protected String getAllLobKey() { + return "LOB"; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/LockingHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/LockingHandler.java new file mode 100644 index 0000000000..592e45f1d1 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/LockingHandler.java @@ -0,0 +1,167 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.lock.CDOLockUtil; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.internal.couchbase.marshall.JSONLockArea; +import org.eclipse.emf.cdo.spi.server.InternalLockManager; +import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class LockingHandler extends JSONHandler { + + public LockingHandler(CouchbaseClient client, IStore store) { + super(client, store); + } + + public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException + { + JSONLockArea primitive = readJSONLockArea(durableLockingID); + if (primitive != null) { + return JSONLockArea.getLockArea(getStore(), primitive); + } + throw new LockAreaNotFoundException(durableLockingID); + } + + public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks) + { + String durableLockingID = getNextDurableLockingID(); + LockArea lockArea = CDOLockUtil.createLockArea(durableLockingID, userID, branchPoint, readOnly, locks); + storeLockArea(lockArea); + return lockArea; + } + + public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock) + { + // TODO Refactor. Next chunk of code copied verbatim from MEMStore.lock + LockArea area = getLockArea(durableLockingID); + Map<CDOID, LockGrade> locks = area.getLocks(); + + InternalLockManager lockManager = (InternalLockManager)getStore().getRepository().getLockingManager(); + for (Object objectToLock : objectsToLock) + { + CDOID id = lockManager.getLockKeyID(objectToLock); + LockGrade grade = locks.get(id); + if (grade != null) + { + grade = grade.getUpdated(type, true); + } + else + { + grade = LockGrade.get(type); + } + + locks.put(id, grade); + } + + storeLockArea(area); + } + + public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock) { + // TODO (CD) Refactor? Next chunk of code copied verbatim from MEMStore.lock + LockArea area = getLockArea(durableLockingID); + Map<CDOID, LockGrade> locks = area.getLocks(); + InternalLockManager lockManager = (InternalLockManager) getStore() .getRepository().getLockingManager(); + for (Object objectToUnlock : objectsToUnlock) { + CDOID id = lockManager.getLockKeyID(objectToUnlock); + LockGrade grade = locks.get(id); + if (grade != null) { + grade = grade.getUpdated(type, false); + if (grade == LockGrade.NONE) { + locks.remove(id); + } else { + locks.put(id, grade); + } + } + } + + storeLockArea(area); + } + + public void unlock(String durableLockingID) { + LockArea area = getLockArea(durableLockingID); + Map<CDOID, LockGrade> locks = area.getLocks(); + locks.clear(); + storeLockArea(area); + } + + // FIXME if user id is a prefix, and not the full userID, this method will fail + public void getLockAreas(String userIDPrefix, Handler handler) { + // the framework requests with userIDPrefix == "" to + // get all the persisted locks + List<String> lockIds = userIDPrefix.length() == 0 ? getMultiValue(getAllLocksKey()) : getMultiValue(getLockUserKey(userIDPrefix)); + for (String lockId : lockIds) { + System.out.println(); + LockArea lockArea = getLockArea(lockId); + handler.handleLockArea(lockArea); + } + } + + public void deleteLockArea(final String durableLockingID) { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + LockArea lockArea = getLockArea(durableLockingID); + doCommit(durableLockingID, null, null, PersistMethod.DELETE); + doCommit(getLockUserKey(lockArea), durableLockingID, null, PersistMethod.DELETE_APPENDED); + doCommit(getAllLocksKey(), durableLockingID, null, PersistMethod.DELETE_APPENDED); + } + }.commit(null); + } + + private void storeLockArea(final LockArea area) + { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + JSONLockArea jsonLockArea = JSONLockArea.getJSONLockArea(area); + doCommit(jsonLockArea.getId(), toJson(jsonLockArea), null, PersistMethod.SET); + doCommit(getLockUserKey(area), jsonLockArea.getId(), null, PersistMethod.APPEND_IF_NOT_CONTAINED); + doCommit(getAllLocksKey(), jsonLockArea.getId(), null, PersistMethod.APPEND_IF_NOT_CONTAINED); + } + }.commit(null); + } + + private String getLockUserKey(final LockArea area) { + return getLockUserKey(area.getUserID()); + } + + private String getLockUserKey(final String userName) { + return "LockUser::" + userName; + } + + private String getAllLocksKey() { + return "AllLocks"; + } + + private JSONLockArea readJSONLockArea(String durableLockingID) throws LockAreaNotFoundException + { + String jsonString = (String)getValue(durableLockingID); + if (jsonString != null) { + return fromJson(jsonString, JSONLockArea.class); + } + return null; + } + + // TODO: Refactor -- this was copied verbatim from DurableLockingManager + private String getNextDurableLockingID() { + for (;;) { + String durableLockingID = CDOLockUtil.createDurableLockingID(); + try { + getLockArea(durableLockingID); // Check uniqueness + // Not unique; try once more... + } catch (LockAreaNotFoundException ex) { + return durableLockingID; + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/PackageUnitHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/PackageUnitHandler.java new file mode 100644 index 0000000000..f6bc45c241 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/PackageUnitHandler.java @@ -0,0 +1,53 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.emf.cdo.common.model.EMFUtil; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.internal.couchbase.marshall.JSONPackageUnit; +import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class PackageUnitHandler extends JSONHandler { + + public PackageUnitHandler(CouchbaseClient client, IStore store) { + super(client, store); + } + + protected String getPackageUnitsKey() { + return "CDOPackageUnits"; + } + + public Collection<InternalCDOPackageUnit> readPackageUnits() { + List<String> packageUnits = getMultiValue(getPackageUnitsKey()); + List<InternalCDOPackageUnit> result = new ArrayList<InternalCDOPackageUnit>(); + for(String packageID : packageUnits) { + result.add(readPackageUnit(packageID)); + } + return result; + } + + public InternalCDOPackageUnit readPackageUnit(String id) { + return JSONPackageUnit.getPackageUnit(fromJson((String)getValue(id), JSONPackageUnit.class)); + } + + public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit) { + JSONPackageUnit jsonPackageUnit = fromJson((String)getValue(packageUnit.getTopLevelPackageInfo().getPackageURI()), JSONPackageUnit.class); + return EMFUtil.getAllPackages(jsonPackageUnit.getEPackage()); + } + + public ICommitable createPackageUnitCommitable(final InternalCDOPackageUnit packageUnit) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + JSONPackageUnit jsonPackageUnit = JSONPackageUnit.getJsonPackageUnit(packageUnit, getStore()); + doCommit(getPackageUnitsKey(), packageUnit.getID(), null, PersistMethod.APPEND); + doCommit(packageUnit.getID(), toJson(jsonPackageUnit), null, PersistMethod.SET); + } + }; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/ResourceHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/ResourceHandler.java new file mode 100644 index 0000000000..148623246b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/ResourceHandler.java @@ -0,0 +1,154 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.List; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.eresource.EresourcePackage; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.IStoreAccessor; +import org.eclipse.emf.cdo.server.IStoreAccessor.QueryResourcesContext; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class ResourceHandler extends JSONHandler { + + public ResourceHandler(CouchbaseClient client, IStore store) { + super(client, store); + } + + /** + * We are persisting here: + * - Association folder + name = resourceID + * - Association resourceID = parentFolderID + * - Association resourceID = resourceName + * - List of all resources + */ + public ICommitable createStoreResourceCommitable(final InternalCDORevision revision) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + if (EresourcePackage.eINSTANCE.getCDOResourceNode().isSuperTypeOf(revision.getEClass())) { + String currentName = (String)revision.get(EresourcePackage.eINSTANCE.getCDOResourceNode_Name(), 0); + Long resourceID = (Long)getValue(getResourceIDKey(revision)); + if (resourceID == null || resourceID == CDOIDUtil.getLong(revision.getID())) { + Long formerFolder = (Long)getValue(getResourceFolderKey(revision)); + Long currentFolder = CDOIDUtil.getLong((CDOID)revision.getContainerID()); + formerFolder = formerFolder != null ? formerFolder : currentFolder; + String formerName = (String)getValue(getResourceNameKey(revision)); + if (currentFolder != formerFolder || formerName != currentName) { // this updates data in case path changed + doCommit(getAllResourceKey(), getResourceIDKey(formerFolder, formerName), revision.getID(), PersistMethod.DELETE_APPENDED); + doCommit(getResourceIDKey(formerFolder, formerName), null, null, PersistMethod.DELETE); + } + doCommit(getResourceIDKey(revision), getResourceID(revision), revision.getID(), PersistMethod.SET); + doCommit(getResourceFolderKey(revision), CDOIDUtil.getLong((CDOID)revision.getContainerID()), revision.getID(), PersistMethod.SET); + doCommit(getResourceNameKey(revision), currentName == null? "" : currentName, revision.getID(), PersistMethod.SET); + // FIXME APPEND_IF_NOT_CONTAINED is highly inefficient + doCommit(getAllResourceKey(), getResourceIDKey(revision), revision.getID(), PersistMethod.APPEND_IF_NOT_CONTAINED); + } else { + throw new RuntimeException("Duplicate Resource " + currentName); + } + } + } + }; + } + + public ICommitable createDetachResourceCommitable(final InternalCDORevision revision) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + if (EresourcePackage.eINSTANCE.getCDOResourceNode().isSuperTypeOf(revision.getEClass())) { + doCommit(getResourceFolderKey(revision), null, null, PersistMethod.DELETE); + doCommit(getResourceNameKey(revision), null, null, PersistMethod.DELETE); + doCommit(getResourceIDKey(revision), getResourceID(revision), revision.getID(), PersistMethod.DELETE); + doCommit(getAllResourceKey(), getResourceIDKey(revision), revision.getID(), PersistMethod.DELETE_APPENDED); + } + } + }; + } + + protected String getResourceIDKey(InternalCDORevision revision) { + String name = (String)revision.get(EresourcePackage.eINSTANCE.getCDOResourceNode_Name(), 0); + return getResourceIDKey(CDOIDUtil.getLong((CDOID)revision.getContainerID()), name); + } + + protected String getResourceIDKey(long containerID, String resourceName) { + return "CDOResources::" + containerID + "::" + resourceName; + } + + protected String getAllResourceKey() { + return "AllCDOResources"; + } + + protected String getResourceFolderKey(InternalCDORevision revision) { + return getResourceFolderKey(CDOIDUtil.getLong(revision.getID())); + } + + protected String getResourceNameKey(InternalCDORevision revision) { + return getResourceNameKey(CDOIDUtil.getLong(revision.getID())); + } + + protected String getResourceFolderKey(long resourceID) { + return "CDOResourceFolder::" + resourceID; + } + + protected String getResourceNameKey(long resourceID) { + return "CDOResourceName::" + resourceID; + } + + protected Long getResourceID(InternalCDORevision revision) { + return CDOIDUtil.getLong(revision.getID()); + } + + protected String getResourceKey(IStoreAccessor.QueryResourcesContext context) { + final long folderID = CDOIDUtil.getLong(context.getFolderID()); + final String name = context.getName(); + return getResourceIDKey(folderID, name); + } + + private String getNameFromID(String resourceID) { + String[] splitted = resourceID.split("::"); + return splitted[2]; + } + + private Long getFolderFromID(String resourceID) { + String[] splitted = resourceID.split("::"); + return Long.parseLong(splitted[1]); + } + + private void addExistingResourceToContext(QueryResourcesContext context, + String resourceID) { + Long result = (Long)getValue(resourceID); + if (result != null) { + CDOID id = CDOIDUtil.createLong(result); + context.addResource(id); + } + } + + public void queryResources(QueryResourcesContext context) { + final boolean exactMatch = context.exactMatch(); + if (exactMatch) { + Long result = (Long)getValue(getResourceKey(context)); + if (result != null) { + CDOID id = CDOIDUtil.createLong(result); + context.addResource(id); + } + } else { + // FIXME This is not efficient, maybe implement with Couchbase queries? + List<String> resourceIDs = getMultiValue(getAllResourceKey()); + CDOID folderID = context.getFolderID(); + for (String resourceID : resourceIDs) { + if (getNameFromID(resourceID).startsWith(context.getName())) { + if (folderID != null && folderID != CDOID.NULL) { + if (CDOIDUtil.getLong(folderID) == getFolderFromID(resourceID)) { + addExistingResourceToContext(context, resourceID); + } + } else { + // if no folder restriction is not defined in the context, we check all resources + addExistingResourceToContext(context, resourceID); + } + } + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/RevisionHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/RevisionHandler.java new file mode 100644 index 0000000000..00aa1b05c7 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/RevisionHandler.java @@ -0,0 +1,175 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.ArrayList; +import java.util.List; + +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.CDOIDUtil; +import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; +import org.eclipse.emf.cdo.server.internal.couchbase.marshall.JSONRevision; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.net4j.util.ObjectUtil; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class RevisionHandler extends JSONHandler { + + private ResourceHandler resourceHandler; + + public RevisionHandler(CouchbaseClient client, IStore store) { + super(client, store); + resourceHandler = new ResourceHandler(getClient(), getStore()); + } + + public ICommitable createRevisionWriteCommitable(final InternalCDORevision revision) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + resourceHandler.createStoreResourceCommitable(revision).commit(monitor); + JSONRevision rev = JSONRevision.getJSONRevision(revision); + doCommit(getRevisionByIdAndBranchKey(revision), toJson(rev), revision.getID(), PersistMethod.SET); + //FIXME modeling this information as lists wont scale well, and introduces overhead on writting, and this info is not requested usually + // Investigate Couchbase queries + doCommit(getRevisionByEClassKey(revision), CDOIDUtil.getLong(revision.getID()), revision.getID(), PersistMethod.APPEND_IF_NOT_CONTAINED); + doCommit(getRevisionByEClassAndBranchKey(revision), CDOIDUtil.getLong(revision.getID()), revision.getID(), PersistMethod.APPEND_IF_NOT_CONTAINED); + doCommit(getAllRevisionInBranchKey(revision.getBranch()), CDOIDUtil.getLong(revision.getID()), revision.getID(), PersistMethod.APPEND_IF_NOT_CONTAINED); + } + }; + } + + public ICommitable createRevisionDetachCommitable(final CDOID id, final CDOBranch branch) { + return new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + InternalCDORevision revision = readRevision(id, branch); + resourceHandler.createDetachResourceCommitable(revision).commit(monitor); + doCommit(getRevisionByIdAndBranchKey(revision), null, id, PersistMethod.DELETE); + doCommit(getRevisionByEClassKey(revision), CDOIDUtil.getLong(id), id, PersistMethod.DELETE_APPENDED); + doCommit(getRevisionByEClassAndBranchKey(revision), CDOIDUtil.getLong(id), id, PersistMethod.DELETE_APPENDED); + doCommit(getAllRevisionInBranchKey(revision.getBranch()), CDOIDUtil.getLong(revision.getID()), revision.getID(), PersistMethod.DELETE_APPENDED); + } + }; + } + + public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint) { + return readRevision(id, branchPoint.getBranch()); + } + + public InternalCDORevision readRevision(CDOID id, CDOBranch branch) { + String key = getRevisionByIdAndBranchKey(id, branch); + String jsonString = (String)getValue(key); + if (jsonString == null) { + return null; + } + JSONRevision revision = fromJson(jsonString, JSONRevision.class); + return JSONRevision.getCDORevision(getStore(), revision); + } + + public List<CDOID> readAllRevisionsInBranch(CDOBranch branch) { + return getCDOIDList(getMultiValue(getAllRevisionInBranchKey(branch))); + } + + public List<CDOID> readAllRevisionsOfEClassInBranch(EClass eClass, CDOBranch branch) { + return getCDOIDList(getMultiValue(getRevisionByEClassAndBranchKey(eClass, branch))); + } + + public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime, CDORevisionHandler handler) { + for (CDOID id : eClass != null ? readAllRevisionsOfEClassInBranch(eClass, branch) : readAllRevisionsInBranch(branch)) { + InternalCDORevision revision = readRevision(id, branch); + if (timeStamp != CDOBranchPoint.INVALID_DATE) + { + if (exactTime) + { + if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE && revision.getTimeStamp() != timeStamp) + { + continue; + } + } + else + { + if (!revision.isValid(timeStamp)) + { + continue; + } + } + } + handler.handleRevision(revision); + } + } + + private List<CDOID> getCDOIDList(List<String> cdoids) { + List<CDOID> ids = new ArrayList<CDOID>(); + for (String id : cdoids) { + CDOID cdoid = CDOIDUtil.createLong(Long.parseLong(id)); + ids.add(cdoid); + } + return ids; + } + + protected String getRevisionByIdAndBranchKey(InternalCDORevision revision) { + return getRevisionByIdAndBranchKey(revision.getID(), revision.getBranch()); + } + + protected String getRevisionByIdAndBranchKey(CDOID id, CDOBranch branch) { + return "CDORevision::" + branch.getName() + "::" + CDOIDUtil.getLong(id); + } + + protected String getRevisionByEClassKey(InternalCDORevision revision) { + return getRevisionByEClassKey(revision.getEClass()); + } + + protected String getRevisionByEClassKey(EClass eClass) { + return "RevisionByEClass::" + eClass.getEPackage().getNsURI() + "::" + eClass.getName(); + } + + protected String getRevisionByEClassAndBranchKey(InternalCDORevision revision) { + return getRevisionByEClassAndBranchKey(revision.getEClass(), revision.getBranch()); + } + + protected String getRevisionByEClassAndBranchKey(EClass eClass, CDOBranch branch) { + return "RevisionByEClassAndBranch::" + eClass.getEPackage().getNsURI() + + "::" + eClass.getName() + branch.getName(); + } + + protected String getAllRevisionInBranchKey(CDOBranch branch) { + return "AllCDORevision::" + branch.getName(); + } + + public void queryXRefs(QueryXRefsContext context) { + final CDOBranch branch = context.getBranch(); + for (final CDOID target : context.getTargetObjects().keySet()) + { + for (final EClass eClass : context.getSourceCandidates().keySet()) + { + final List<EReference> eReferences = context.getSourceCandidates().get(eClass); + for (EReference eReference : eReferences) { + List<String> byEClassIds = getMultiValue(getRevisionByEClassKey(eClass)); + for (String id : byEClassIds) { + CDOID source = CDOIDUtil.createLong(Long.parseLong(id)); + InternalCDORevision revision = readRevision(source, branch); + Object obj = revision.getValue(eReference); + if (obj instanceof CDOID) { + if (ObjectUtil.equals(obj, target)) { + context.addXRef(target, source, eReference, 0); + } + } else if (obj instanceof List<?>) { + int index = 0; + for (Object objFromList :(List<?>)obj) { + if (ObjectUtil.equals(objFromList, target)) { + context.addXRef(target, source, eReference, index); + } + ++index; + } + } + } + } + } + } + } + +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/StoreHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/StoreHandler.java new file mode 100644 index 0000000000..60dde58809 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/StoreHandler.java @@ -0,0 +1,19 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import org.eclipse.emf.cdo.server.IStore; + +import com.couchbase.client.CouchbaseClient; + +public class StoreHandler extends CouchbaseHandler { + + private IStore store; + + public StoreHandler(CouchbaseClient client, IStore store) { + super(client); + this.store = store; + } + + protected IStore getStore() { + return store; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/StoreMetaHandler.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/StoreMetaHandler.java new file mode 100644 index 0000000000..22c1a62a7d --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/commitables/StoreMetaHandler.java @@ -0,0 +1,151 @@ +package org.eclipse.emf.cdo.server.internal.commitables; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import com.couchbase.client.CouchbaseClient; + +public class StoreMetaHandler extends CouchbaseHandler { + + public StoreMetaHandler(CouchbaseClient client) { + super(client); + } + + public Long getLastCDOID() { + return (Long)getValue(getLastCDOIDKey()); + } + + public Boolean isFirstStart() { + Boolean result = (Boolean)getValue(getIsFirstStartKey()); + if (result != null) { + return result; + } + return true; + } + + public void setLastCDOID(final Long lastCDOID) { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + doCommit(getLastCDOIDKey(), lastCDOID, null, PersistMethod.SET); + } + }.commit(null); + } + + public void setIsFirstStart(final Boolean firstStart) { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + doCommit(getIsFirstStartKey(), firstStart, null, PersistMethod.SET); + } + }.commit(null); + } + + public Long getCreationTime() { + Long value = (Long)getValue(getCreationTimeKey()); + if (value != null) { + return value; + } + value = System.currentTimeMillis(); + setCreationTime(value); + return value; + } + + public void setCreationTime(final long creationTime) { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + doCommit(getCreationTimeKey(), creationTime, null, PersistMethod.SET); + } + }.commit(null); + } + + public Long getLastCommitTime() { + Long value = (Long)getValue(getLastCommitTimeKey()); + if (value != null) { + return value; + } + return 0l; + } + + public void setLastCommitTime(final long commitTime) { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + doCommit(getLastCommitTimeKey(), commitTime, null, PersistMethod.SET); + } + }.commit(null); + } + + public Map<String, String> getPersistentProperties(Set<String> names) { + + if (names == null || names.isEmpty()) + { + List<String> propertyKeys = getMultiValue(getAllPropertyKey()); + Map<String, String> result = new HashMap<String, String>(); + for (String propertyKey : propertyKeys) { + result.put(propertyKey, (String)getValue(getPropertyKey(propertyKey))); + } + return result; + } + + Map<String, String> result = new HashMap<String, String>(); + for (String key : names) + { + String value = (String)getValue(getPropertyKey(key)); + if (value != null) + { + result.put(key, value); + } + } + + return result; + } + + public void setPersistentProperties(final Map<String, String> properties) { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + for (String key : properties.keySet()) { + doCommit(getPropertyKey(key), properties.get(key), null, PersistMethod.SET); + doCommit(getAllPropertyKey(), key, null, PersistMethod.APPEND_IF_NOT_CONTAINED); + } + } + }.commit(null); + + } + + public void removePersistentProperties(final Set<String> names) { + new AbstractCommitable(getClient()) { + public void commit(OMMonitor monitor) { + for (String key : names) { + doCommit(getPropertyKey(key), null, null, PersistMethod.DELETE); + doCommit(getAllPropertyKey(), key, null, PersistMethod.DELETE_APPENDED); + } + } + }.commit(null); + } + + private String getLastCDOIDKey() { + return "lastCDOID"; + } + + private String getIsFirstStartKey() { + return "isFirstStart"; + } + + private String getCreationTimeKey() { + return "creationTime"; + } + + private String getLastCommitTimeKey() { + return "lastCommitTime"; + } + + private String getAllPropertyKey() { + return "AllStoreProperties"; + } + + private String getPropertyKey(String key) { + return "StoreProperty::" + key; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/bundle/OM.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/bundle/OM.java new file mode 100644 index 0000000000..20138f420a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/bundle/OM.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2013 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: + * Victor Roldan Betancort - initial API and implementation + */ + +package org.eclipse.emf.cdo.server.internal.couchbase.bundle; + +import org.eclipse.net4j.util.om.OMBundle; +import org.eclipse.net4j.util.om.OMPlatform; +import org.eclipse.net4j.util.om.OSGiActivator; +import org.eclipse.net4j.util.om.log.OMLogger; +import org.eclipse.net4j.util.om.trace.OMTracer; + +/** + * The <em>Operations & Maintenance</em> class of this bundle. + * + * @author Victor Roldan Betancort + */ +public abstract class OM +{ + public static final String BUNDLE_ID = "org.eclipse.emf.cdo.server.couchbase"; //$NON-NLS-1$ + + public static final OMBundle BUNDLE = OMPlatform.INSTANCE.bundle(BUNDLE_ID, OM.class); + + public static final OMTracer DEBUG = BUNDLE.tracer("debug"); //$NON-NLS-1$ + + public static final OMLogger LOG = BUNDLE.logger(); + + /** + * @author Victor Roldan Betancort + */ + public static final class Activator extends OSGiActivator + { + public Activator() + { + super(BUNDLE); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockArea.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockArea.java new file mode 100644 index 0000000000..56ecea43c4 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockArea.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2011-2013 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: + * Caspar De Groot - initial API and implementation + */ +package org.eclipse.emf.cdo.server.internal.couchbase.marshall; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +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.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.lock.CDOLockUtil; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade; +import org.eclipse.emf.cdo.server.IStore; + +/** + * @author Victor Roldan Betancort TODO Verbatim copy of DB4OLockArea. Refactor + */ +public class JSONLockArea { + + private String id; + + private String userID; + + private long timestamp; + + private int branchID; + + private boolean readOnly; + + private List<JSONLockEntry> lockEntries = new LinkedList<JSONLockEntry>(); + + public static JSONLockArea getJSONLockArea(LockArea lockArea) { + JSONLockArea jsonLockArea = new JSONLockArea(); + + jsonLockArea.setId(lockArea.getDurableLockingID()); + jsonLockArea.setUserID(lockArea.getUserID()); + jsonLockArea.setTimestamp(lockArea.getTimeStamp()); + jsonLockArea.setBranchID(lockArea.getBranch().getID()); + jsonLockArea.setReadOnly(lockArea.isReadOnly()); + + List<JSONLockEntry> newList = JSONLockEntry.getPrimitiveLockEntries(jsonLockArea, lockArea.getLocks()); + jsonLockArea.setLockEntries(newList); + + return jsonLockArea; + } + + public static LockArea getLockArea(IStore store, JSONLockArea jsonLockArea) { + // Reconstruct the branchpoint + // + CDOBranchManager branchManager = store.getRepository().getBranchManager(); + CDOBranch branch = branchManager.getBranch(jsonLockArea.getBranchID()); + CDOBranchPoint branchpoint = branch.getPoint(jsonLockArea.getTimestamp()); + + // Reconstruct the lockMap + // + Map<CDOID, LockGrade> lockMap = CDOIDUtil.createMap(); + for (JSONLockEntry entry : jsonLockArea.getLockEntries()) { + CDOID cdoid = CDOIDUtil.createLong(entry.getCdoID()); + LockGrade lockGrade = LockGrade.get(entry.getLockGrade()); + lockMap.put(cdoid, lockGrade); + } + + return CDOLockUtil.createLockArea(jsonLockArea.getId(), + jsonLockArea.getUserID(), branchpoint, + jsonLockArea.isReadOnly(), lockMap); + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public String getUserID() { + return userID; + } + + public long getTimestamp() { + return timestamp; + } + + public int getBranchID() { + return branchID; + } + + public List<JSONLockEntry> getLockEntries() { + return lockEntries; + } + + public boolean isReadOnly() { + return readOnly; + } + + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + public void setUserID(String userID) { + this.userID = userID; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public void setBranchID(int branchID) { + this.branchID = branchID; + } + + private void setLockEntries(List<JSONLockEntry> lockEntries) { + this.lockEntries = lockEntries; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockAreaTypeAdapter.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockAreaTypeAdapter.java new file mode 100644 index 0000000000..ffb88fdfd9 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockAreaTypeAdapter.java @@ -0,0 +1,66 @@ +package org.eclipse.emf.cdo.server.internal.couchbase.marshall; + +import java.lang.reflect.Type; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +public class JSONLockAreaTypeAdapter implements JsonDeserializer<JSONLockArea>, + JsonSerializer<JSONLockArea> { + + private static final String ID = "id"; + private static final String USER_ID = "user_id"; + private static final String BRANCH_ID = "branch_id"; + private static final String TIMESTAMP = "timestamp"; + private static final String READONLY = "readonly"; + private static final String ENTRY_CDOID = "entry_cdoid_"; + private static final String ENTRY_GRADE = "entry_grade_"; + + public JsonElement serialize(JSONLockArea arg0, Type arg1, JsonSerializationContext arg2) { + JsonObject obj = new JsonObject(); + obj.addProperty(ID, arg0.getId()); + obj.addProperty(USER_ID, arg0.getUserID()); + obj.addProperty(BRANCH_ID, arg0.getBranchID()); + obj.addProperty(TIMESTAMP, arg0.getTimestamp()); + obj.addProperty(READONLY, arg0.isReadOnly()); + int count = 0; + for (JSONLockEntry entry : arg0.getLockEntries()) { + obj.addProperty(getEntryCDOIDKey(count), entry.getCdoID()); + obj.addProperty(getEntryGradeKey(count), entry.getLockGrade()); + count++; + } + return obj; + } + + public JSONLockArea deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2) throws JsonParseException { + JSONLockArea jsonLockArea = new JSONLockArea(); + JsonObject json = (JsonObject) arg0; + jsonLockArea.setId(json.get(ID).getAsString()); + jsonLockArea.setUserID(json.get(USER_ID).getAsString()); + jsonLockArea.setBranchID(json.get(BRANCH_ID).getAsInt()); + jsonLockArea.setTimestamp(json.get(TIMESTAMP).getAsLong()); + jsonLockArea.setReadOnly(json.get(READONLY).getAsBoolean()); + for (int i = 0; true; i++) { + if (json.get(getEntryCDOIDKey(i)) != null) { + jsonLockArea.getLockEntries().add(new JSONLockEntry(json.get(getEntryCDOIDKey(i)) + .getAsLong(), json.get(getEntryGradeKey(i)).getAsInt())); + } else { + break; + } + } + return jsonLockArea; + } + + private String getEntryCDOIDKey(int count) { + return ENTRY_CDOID + count; + } + + private String getEntryGradeKey(int count) { + return ENTRY_GRADE + count; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockEntry.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockEntry.java new file mode 100644 index 0000000000..71c8d6144b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONLockEntry.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2011, 2012 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: + * Caspar De Groot - initial API and implementation + */ +package org.eclipse.emf.cdo.server.internal.couchbase.marshall; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * @author Victor Roldan Betancort + * TODO Verbatim copy of DB4OLockArea. Refactor + */ +public class JSONLockEntry +{ + private long cdoID; + + private int lockGrade; + + public JSONLockEntry(long longCdoID, int intLockGrade) + { + cdoID = longCdoID; + lockGrade = intLockGrade; + } + + public static List<JSONLockEntry> getPrimitiveLockEntries(JSONLockArea jsonLockArea, Map<CDOID, LockGrade> locks) + { + List<JSONLockEntry> newList = new LinkedList<JSONLockEntry>(); + + for (Entry<CDOID, LockGrade> entry : locks.entrySet()) + { + CDOID cdoid = entry.getKey(); + long longCdoID = CDOIDUtil.getLong(cdoid); + + LockGrade lockGrade = entry.getValue(); + int intLockGrade = lockGrade.getValue(); + + JSONLockEntry lockEntry = getEntry(jsonLockArea.getLockEntries(), longCdoID); + if (lockEntry == null) + { + lockEntry = new JSONLockEntry(longCdoID, intLockGrade); + } + else + { + lockEntry.setLockGrade(intLockGrade); + } + + newList.add(lockEntry); + } + + return newList; + } + + private void setLockGrade(int lockGrade) + { + this.lockGrade = lockGrade; + } + + // TODO (CD) Avoid linear search + private static JSONLockEntry getEntry(List<JSONLockEntry> entries, long targetID) + { + for (JSONLockEntry entry : entries) + { + if (entry.cdoID == targetID) + { + return entry; + } + } + + return null; + } + + public long getCdoID() + { + return cdoID; + } + + public int getLockGrade() + { + return lockGrade; + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONPackageUnit.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONPackageUnit.java new file mode 100644 index 0000000000..8ae8cea174 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONPackageUnit.java @@ -0,0 +1,154 @@ +package org.eclipse.emf.cdo.server.internal.couchbase.marshall; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.cdo.common.model.CDOModelUtil; +import org.eclipse.emf.cdo.common.model.CDOPackageRegistry; +import org.eclipse.emf.cdo.common.model.CDOPackageUnit; +import org.eclipse.emf.cdo.common.model.EMFUtil; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo; +import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl; +import org.eclipse.net4j.util.collection.Pair; + +public class JSONPackageUnit { + + private String id; + + private Integer originalType; + + private Long timeStamp; + + private List<Byte> ePackageBytes; + + private List<Pair<String, String>> packageInfos; + + public JSONPackageUnit(String id, Integer originalType, Long timeStamp, + List<Byte> ePackageBytes, List<Pair<String, String>> packageIntos) { + this.setId(id); + this.setOriginalType(originalType); + this.setTimeStamp(timeStamp); + this.setEPackageBytes(ePackageBytes); + this.setPackageInfos(packageIntos); + } + + public String getId() { + return id; + } + + public Integer getOriginalType() { + return originalType; + } + + public Long getTimeStamp() { + return timeStamp; + } + + public List<Byte> getEPackageBytes() { + return ePackageBytes; + } + + public List<Pair<String, String>> getPackageInfos() { + return packageInfos; + } + + public void setId(String id) { + this.id = id; + } + + public void setOriginalType(Integer originalType) { + this.originalType = originalType; + } + + public void setTimeStamp(Long timeStamp) { + this.timeStamp = timeStamp; + } + + public void setEPackageBytes(List<Byte> ePackageBytes) { + this.ePackageBytes = ePackageBytes; + } + + public void setPackageInfos(List<Pair<String, String>> packageInfos) { + this.packageInfos = packageInfos; + } + + public EPackage getEPackage() { + return getEPackageFromBytes(getEPackageBytes()); + } + + public static InternalCDOPackageUnit getPackageUnit(JSONPackageUnit jsonPackageUnit) { + InternalCDOPackageUnit cdoPackageUnit = (InternalCDOPackageUnit) CDOModelUtil.createPackageUnit(); + cdoPackageUnit.setOriginalType(CDOPackageUnit.Type.values()[jsonPackageUnit.getOriginalType()]); + cdoPackageUnit.setTimeStamp(jsonPackageUnit.getTimeStamp()); + cdoPackageUnit.setPackageInfos(getPackageInfos(jsonPackageUnit.getPackageInfos())); + return cdoPackageUnit; + } + + public static JSONPackageUnit getJsonPackageUnit(InternalCDOPackageUnit packageUnit, IStore store) { + String id = new String(packageUnit.getID()); + Integer originalType = new Integer(packageUnit.getOriginalType().ordinal()); + Long timeStamp = new Long(packageUnit.getTimeStamp()); + List<Byte> ePackageBytes = getEPackageBytes(store, packageUnit); + List<Pair<String, String>> packageInfos = getPackageInfosAsPair(packageUnit.getPackageInfos()); + return new JSONPackageUnit(id, originalType, timeStamp, ePackageBytes, packageInfos); + + } + + private static EPackage getEPackageFromBytes(List<Byte> ePackageBytesList) { + ResourceSet rSet = new ResourceSetImpl(); + Resource.Factory resourceFactory = new EcoreResourceFactoryImpl(); + rSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", resourceFactory); //$NON-NLS-1$ + byte[] packageBytes = new byte[ePackageBytesList.size()]; + for (int i = 0; i < packageBytes.length; i++) { + packageBytes[i] = ePackageBytesList.get(i); + } + EPackage ePackage = EMFUtil.createEPackage("", packageBytes, true, rSet, false); + return ePackage; + } + + private static List<Byte> getEPackageBytes(IStore store, + InternalCDOPackageUnit packageUnit) { + EPackage ePackage = packageUnit.getTopLevelPackageInfo().getEPackage(); + CDOPackageRegistry packageRegistry = store.getRepository() + .getPackageRegistry(); + byte[] bytes = EMFUtil + .getEPackageBytes(ePackage, true, packageRegistry); + List<Byte> bytesObject = new ArrayList<Byte>(); + for (byte bt : bytes) { + bytesObject.add(new Byte(bt)); + } + + return bytesObject; + } + + private static List<Pair<String, String>> getPackageInfosAsPair( + InternalCDOPackageInfo[] packageInfos) { + List<Pair<String, String>> infos = new ArrayList<Pair<String, String>>(); + for (InternalCDOPackageInfo info : packageInfos) { + Pair<String, String> pair = Pair.create(info.getParentURI(), + info.getPackageURI()); + infos.add(pair); + } + + return infos; + } + + private static InternalCDOPackageInfo[] getPackageInfos( + List<Pair<String, String>> packagePairs) { + List<InternalCDOPackageInfo> list = new ArrayList<InternalCDOPackageInfo>(); + for (Pair<String, String> infoPair : packagePairs) { + InternalCDOPackageInfo packageInfo = (InternalCDOPackageInfo) CDOModelUtil + .createPackageInfo(); + packageInfo.setParentURI(infoPair.getElement1()); + packageInfo.setPackageURI(infoPair.getElement2()); + list.add(packageInfo); + } + return list.toArray(new InternalCDOPackageInfo[list.size()]); + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONRevision.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONRevision.java new file mode 100644 index 0000000000..4a684b3057 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONRevision.java @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2010-2012 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: + * Victor Roldan Betancort - initial API and implementation + */ + +package org.eclipse.emf.cdo.server.internal.couchbase.marshall; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.cdo.common.branch.CDOBranch; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDExternal; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.model.CDOClassInfo; +import org.eclipse.emf.cdo.common.revision.CDOList; +import org.eclipse.emf.cdo.common.revision.CDOListFactory; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionData; +import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; +import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; +import org.eclipse.emf.cdo.server.IRepository; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureMapEntry; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.util.FeatureMap; + +import com.google.gson.JsonNull; + +/** + * @author Victor Roldan Betancort + */ +public class JSONRevision +{ + public final static String ATTRIBUTE_CLASS_NAME = "className"; + + public final static String ATTRIBUTE_PACKAGE_NS_URI = "packageNsURI"; + + private String packageNsURI; + + private String className; + + private long id; + + private int version; + + private long timeStamp; + + private long resourceID; + + /** + * Can be an external ID! + */ + private Object containerID; + + private int containingFeatureID; + + private List<Object> values; + + // TODO enum RevisionType { NORMAL, ROOT_RESOURCE, RESOURCE, RESOURCE_FOLDER }?? + private boolean isResource; + + private boolean isResourceFolder; + + public JSONRevision() { + + } + + public JSONRevision(String packageURI, String className, long id, int version, long resourceID, Object containerID, + int containingFeatureID, List<Object> values, long timestamp, boolean isResource, boolean isResourceFolder) + { + setPackageURI(packageURI); + setClassName(className); + setID(id); + setVersion(version); + setResourceID(resourceID); + setContainerID(containerID); + setContainingFeatureID(containingFeatureID); + setValues(values); + setTimeStamp(timestamp); + setResource(isResource); + setResourceFolder(isResourceFolder); + } + + public void setPackageURI(String packageURI) + { + packageNsURI = packageURI; + } + + public String getPackageURI() + { + return packageNsURI; + } + + public void setClassName(String className) + { + this.className = className; + } + + public String getClassName() + { + return className; + } + + public void setID(long id) + { + this.id = id; + } + + public long getID() + { + return id; + } + + public void setVersion(int version) + { + this.version = version; + } + + public int getVersion() + { + return version; + } + + public long getRevised() + { + return CDORevision.UNSPECIFIED_DATE; + } + + public void setResourceID(long resourceID) + { + this.resourceID = resourceID; + } + + public long getResourceID() + { + return resourceID; + } + + public void setContainerID(Object containerID) + { + this.containerID = containerID; + } + + public Object getContainerID() + { + return containerID; + } + + public void setContainingFeatureID(int containingFeatureID) + { + this.containingFeatureID = containingFeatureID; + } + + public int getContainingFeatureID() + { + return containingFeatureID; + } + + public void setValues(List<Object> values) + { + this.values = values; + } + + public List<Object> getValues() + { + return values; + } + + public void setTimeStamp(long timeStamp) + { + this.timeStamp = timeStamp; + } + + public long getTimeStamp() + { + return timeStamp; + } + + public void setResource(boolean isResource) + { + this.isResource = isResource; + } + + public boolean isResource() + { + return isResource; + } + + public void setResourceFolder(boolean isResourceFolder) + { + this.isResourceFolder = isResourceFolder; + } + + public boolean isResourceFolder() + { + return isResourceFolder; + } + + public boolean isResourceNode() + { + return isResource || isResourceFolder; + } + + public static JSONRevision getJSONRevision(InternalCDORevision revision) + { + CDOClassInfo classInfo = revision.getClassInfo(); + EClass eClass = classInfo.getEClass(); + String packageURI = eClass.getEPackage().getNsURI(); + String className = eClass.getName(); + + CDOID revisionID = revision.getID(); + if (revisionID.isTemporary()) + { + throw new IllegalArgumentException("TEMPORARY CDOID: " + revisionID); + } + + boolean isResource = revision.isResource(); + boolean isResourceFolder = revision.isResourceFolder(); + + long id = CDOIDUtil.getLong(revisionID); + int version = revision.getVersion(); + long timeStamp = revision.getTimeStamp(); + long resourceID = CDOIDUtil.getLong(revision.getResourceID()); + Object containerID = getJSONID((CDOID)revision.getContainerID()); + int containingFeatureID = revision.getContainingFeatureID(); + + EStructuralFeature[] features = classInfo.getAllPersistentFeatures(); + List<Object> values = new ArrayList<Object>(features.length); + if (features.length > 0) + { + for (int i = 0; i < features.length; i++) + { + EStructuralFeature feature = features[i]; + Object obj = revision.getValue(feature); + + // We will process CDOList for EReferences to get rid of CDOIDs (we want to get only primitive types, + // otherwise the JSON Converter will mess up certain classes + + // Multi-valued EAttributes (also kept in CDOList) will be saved as is + if (feature instanceof EReference) + { + if (feature.isMany()) { + InternalCDOList cdoList = (InternalCDOList)obj; + List<Object> list = new ArrayList<Object>(); + // if the multivalued reference is empty, it would be null + if (obj != null) { + for (Object listElement : cdoList) + { + if (!(listElement instanceof CDOID)) + { + throw new IllegalStateException("CDOList should contain only CDOID instances but received " + + listElement.getClass().getName() + " instead"); + } + + list.add(getJSONID((CDOID)listElement)); + } + } + values.add(i, list); + } else { + if (obj != null) { + values.add(i, getJSONID((CDOID)obj)); + } else { + values.add(i, null); + } + } + } + else if (listContainsInstancesOfClass(obj, CDOFeatureMapEntry.class)) // FeatureMap + { + values.add(i, JSONFeatureMapEntry.getPrimitiveFeatureMapEntryList(obj)); + } + else // Process EAttribute + { + // Prevent the explicit null-ref "NIL" from being serialized! + if (obj == CDORevisionData.NIL) + { + obj = new ExplicitNull(); + } + if (obj instanceof CDOID) { + System.out.println("This should not happen"); + } else { + values.add(i, obj); + } + } + } + } + + return new JSONRevision(packageURI, className, id, version, resourceID, containerID, containingFeatureID, values, + timeStamp, isResource, isResourceFolder); + } + + public static InternalCDORevision getCDORevision(IStore store, JSONRevision primitiveRevision) + { + IRepository repository = store.getRepository(); + CDORevisionFactory factory = ((InternalCDORevisionManager)repository.getRevisionManager()).getFactory(); + CDOBranch branch = repository.getBranchManager().getMainBranch(); + + String nsURI = primitiveRevision.getPackageURI(); + String className = primitiveRevision.getClassName(); + EPackage ePackage = repository.getPackageRegistry().getEPackage(nsURI); + EClass eClass = (EClass)ePackage.getEClassifier(className); + InternalCDORevision revision = (InternalCDORevision)factory.createRevision(eClass); + + revision.setID(getCDOID(primitiveRevision.getID())); + revision.setVersion(primitiveRevision.getVersion()); + revision.setBranchPoint(branch.getPoint(primitiveRevision.getTimeStamp())); + revision.setRevised(primitiveRevision.getRevised()); + revision.setResourceID(getCDOID(primitiveRevision.getResourceID())); + revision.setContainerID(getCDOID(primitiveRevision.getContainerID())); + revision.setContainingFeatureID(primitiveRevision.getContainingFeatureID()); + EStructuralFeature[] features = revision.getClassInfo().getAllPersistentFeatures(); + + int i = 0; + for (Object value : primitiveRevision.getValues()) + { + EStructuralFeature feature = features[i++]; + if (feature instanceof EReference) + { + if (feature.isMany()) { + value = getCDOList(value, true); + } else { + value = getCDOID(value); + } + } + else if (feature instanceof EAttribute && feature.isMany()) + { + value = getCDOList(value, false); + } + else if (listContainsInstancesOfClass(value, JSONFeatureMapEntry.class)) + { + value = JSONFeatureMapEntry.getCDOFeatureMapEntryList(eClass, value); + } + + // Convert 'null' into the explicit null-ref "NIL" if appropriate + if (value instanceof ExplicitNull) + { + value = CDORevisionData.NIL; + } + + revision.setValue(feature, value); + } + + return revision; + } + +private static CDOList getCDOList(Object value, boolean isReference) { + List<?> sourceList = (List<?>)value; + CDOList list = CDOListFactory.DEFAULT.createList(sourceList.size(), sourceList.size(), CDORevision.UNCHUNKED); + for (int j = 0; j < sourceList.size(); j++) + { + list.set(j, isReference ? getCDOID(sourceList.get(j)) : sourceList.get(j)); + } + return list; +} + + public static Object getJSONID(CDOID id) + { + if (id.isExternal()) + { + return new String(((CDOIDExternal)id).getURI()); + } + + return CDOIDUtil.getLong(id); + } + + public static CDOID getCDOID(Object id) + { + if (id == null || id instanceof JsonNull) + { + return CDOID.NULL; + } + + if (id instanceof String) + { + String value = (String)id; + value = value.replace("\"", ""); + try { + return CDOIDUtil.createLong(Long.valueOf(value)); + } catch (NumberFormatException e) { + return CDOIDUtil.createExternal(value); + } + } + + if (id instanceof CDOID) + { + return (CDOID)id; + } + + return CDOIDUtil.createLong((Long)id); + } + + public static boolean isNull(Object obj) { + return obj instanceof ExplicitNull; + } + + + public static boolean listContainsInstancesOfClass(Object obj, Class<?> clazz) + { + if (obj instanceof List) + { + List<?> list = (List<?>)obj; + for (Object potentialFeatureMap : list) + { + if (!clazz.isAssignableFrom(potentialFeatureMap.getClass())) + { + return false; + } + } + return true; + } + return false; + } + + private static final class JSONFeatureMapEntry + { + + private int featureID; + + private Object valueID; + + public JSONFeatureMapEntry(int featureID, Object valueID) + { + setFeatureID(featureID); + setValueID(valueID); + } + + private void setFeatureID(int featureID) + { + this.featureID = featureID; + } + + public int getFeatureID() + { + return featureID; + } + + private void setValueID(Object valueID) + { + this.valueID = valueID; + } + + public Object getValueID() + { + return valueID; + } + + public static List<JSONFeatureMapEntry> getPrimitiveFeatureMapEntryList(Object obj) + { + InternalCDOList cdoList = (InternalCDOList)obj; + List<JSONFeatureMapEntry> list = new ArrayList<JSONFeatureMapEntry>(); + for (Object listElement : cdoList) + { + if (listElement instanceof FeatureMap.Entry) + { + FeatureMap.Entry entry = (FeatureMap.Entry)listElement; + EStructuralFeature entryFeature = entry.getEStructuralFeature(); + CDOID entryValue = (CDOID)entry.getValue(); + JSONFeatureMapEntry jsonEntry = new JSONFeatureMapEntry(entryFeature.getFeatureID(), getJSONID(entryValue)); + list.add(jsonEntry); + } + } + return list; + } + + public static CDOList getCDOFeatureMapEntryList(EClass eClass, Object value) + { + List<?> sourceList = (List<?>)value; + CDOList list = CDOListFactory.DEFAULT.createList(sourceList.size(), sourceList.size(), CDORevision.UNCHUNKED); + for (int j = 0; j < sourceList.size(); j++) + { + JSONFeatureMapEntry mapEntry = (JSONFeatureMapEntry)sourceList.get(j); + EStructuralFeature entryFeature = eClass.getEStructuralFeature(mapEntry.getFeatureID()); + CDOID valueID = getCDOID(mapEntry.getValueID()); + list.set(j, CDORevisionUtil.createFeatureMapEntry(entryFeature, valueID)); + } + return list; + } + } + + /** + * @author Caspar De Groot + */ + private static final class ExplicitNull + { + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONRevisionTypeAdapter.java b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONRevisionTypeAdapter.java new file mode 100644 index 0000000000..78dda40f39 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.couchbase/src/org/eclipse/emf/cdo/server/internal/couchbase/marshall/JSONRevisionTypeAdapter.java @@ -0,0 +1,259 @@ +package org.eclipse.emf.cdo.server.internal.couchbase.marshall; + +import java.lang.reflect.Array; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.eclipse.emf.cdo.common.model.CDOModelUtil; +import org.eclipse.emf.cdo.server.IRepository; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EcorePackage; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * Gson is not able to properly serialize JSONRevision, so an adapter + * to manually serialize it is needed. + * + * @author vroldan + * + */ +public class JSONRevisionTypeAdapter implements JsonDeserializer<JSONRevision>, + JsonSerializer<JSONRevision> { + + private static final String FEATURE = "feature_"; + + private static final String CONTAINER_ID = "containerId"; + + private static final String VERSION = "version"; + + private static final String TIMESTAMP = "timestamp"; + + private static final String REVISED = "revised"; + + private static final String RESOURCE_ID = "resourceId"; + + private static final String ID = "id"; + + private static final String CONTAINING_FEATURE_ID = "containingFeatureID"; + + private static final String PACKAGE_URI = "packageURI"; + + private static final String CLASS_NAME = "className"; + + private IStore store; + + private static final String EMPTY_LIST = new String("$_empty_list"); + + public JSONRevisionTypeAdapter(IStore store) { + this.store = store; + } + + public JsonElement serialize(JSONRevision arg0, Type arg1, JsonSerializationContext arg2) { + JsonObject obj = new JsonObject(); + obj.addProperty(CLASS_NAME, arg0.getClassName()); + obj.addProperty(PACKAGE_URI, arg0.getPackageURI()); + obj.addProperty(CONTAINING_FEATURE_ID, arg0.getContainingFeatureID()); + obj.addProperty(ID, arg0.getID()); + obj.addProperty(RESOURCE_ID, arg0.getResourceID()); + obj.addProperty(REVISED, arg0.getRevised()); + obj.addProperty(TIMESTAMP, arg0.getTimeStamp()); + obj.addProperty(VERSION, arg0.getVersion()); + obj.addProperty(CONTAINER_ID, arg0.getContainerID().toString()); + int count = 0; + for (Object value : arg0.getValues()) { + if (value == null) { + obj.addProperty(getFeatureValueID(count), (String)null); + } else if (value instanceof List<?>) { + int nestedCount = 0; + for (Object nestedValue : (List<?>)value) { + obj.addProperty(getNestedFeatureValueID(count, nestedCount), getSerializableValue(nestedValue)); + nestedCount++; + } + if (nestedCount == 0) { + obj.addProperty(getFeatureValueID(count), EMPTY_LIST); + } + } else { + if (value.getClass().isArray()) { + int length = Array.getLength(value); + for (int i = 0; i < length; i ++) { + Object arrayElement = Array.get(value, i); + obj.addProperty(getNestedFeatureValueID(count, i), getSerializableValue(arrayElement)); + } + } else { + obj.addProperty(getFeatureValueID(count), getSerializableValue(value)); + } + } + count++; + } + + return obj; + } + + private String getSerializableValue(Object value) { + if (value == null || JSONRevision.isNull(value)) { + return (String)null; + } else if (value instanceof Date) { + return String.valueOf(((Date)value).getTime()); + } + return value.toString(); + } + + public JSONRevision deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2) throws JsonParseException { + JSONRevision rev = new JSONRevision(); + JsonObject json = (JsonObject)arg0; + rev.setClassName(json.get(CLASS_NAME).getAsString()); + rev.setPackageURI(json.get(PACKAGE_URI).getAsString()); + rev.setContainingFeatureID(json.get(CONTAINING_FEATURE_ID).getAsInt()); + rev.setID(json.get(ID).getAsLong()); + rev.setResourceID(json.get(RESOURCE_ID).getAsLong()); + rev.setTimeStamp(json.get(TIMESTAMP).getAsLong()); + rev.setVersion(json.get(VERSION).getAsInt()); + rev.setContainerID(json.get(CONTAINER_ID).getAsString()); + + IRepository repository = store.getRepository(); + String nsURI = rev.getPackageURI(); + String className = rev.getClassName(); + EPackage ePackage = repository.getPackageRegistry().getEPackage(nsURI); + EClass eClass = (EClass)ePackage.getEClassifier(className); + + int count = 0; + EStructuralFeature[] features = CDOModelUtil.getClassInfo(eClass).getAllPersistentFeatures(); + List<Object> values = new ArrayList<Object>(features.length); + for (EStructuralFeature feature : features) { + if (!feature.isDerived()) { + if (feature.isMany()) { + int nestedCount = 0; + List<Object> nestedList = new ArrayList<Object>(); + JsonElement nestedValue = null; + while (json.has(getNestedFeatureValueID(count, nestedCount))) { + nestedValue = json.get(getNestedFeatureValueID(count, nestedCount)); + nestedList.add(getTypedElement(feature.getEType(), nestedValue, count)); + nestedCount++; + }; + values.add(nestedList); + } else { + if (isByteArray(feature.getEType())) { + values.add(getByteArray(json, count)); + } + else { + values.add(getTypedElement(feature.getEType(), json.get(getFeatureValueID(count)), count)); + } + } + count++; + } + } + rev.setValues(values); + return rev; + } + + private String getFeatureValueID(int count) { + return FEATURE + count; + } + + private String getNestedFeatureValueID(int count, int nestedCount) { + return FEATURE + count + nestedCount; + } + + private boolean isByteArray(EClassifier eType) { + return eType == EcorePackage.eINSTANCE.getEByteArray(); + } + + private Object getByteArray(JsonObject json, int count) { + List<String> arrayList = getArrayValues(json, count); + byte[] byteArray = new byte[arrayList.size()]; + for (int i = 0; i < arrayList.size(); i++) { + byteArray[i] = Byte.valueOf(arrayList.get(i)); + } + return byteArray; + } + + private List<String> getArrayValues(JsonObject json, int count) { + int nestedCount = 0; + List<String> result = new ArrayList<String>(); + while (json.has(getNestedFeatureValueID(count, nestedCount))) { + String nestedValue = json.get(getNestedFeatureValueID(count, nestedCount)).getAsString(); + result.add(nestedValue); + nestedCount++; + }; + return result; + } + + private Object getTypedElement(EClassifier eType, JsonElement jsonElement, int currentCount) { + if (eType instanceof EClass) { + if (jsonElement == null || jsonElement instanceof JsonNull) { + return JSONRevision.getCDOID(jsonElement); + } else { + return JSONRevision.getCDOID(jsonElement.toString()); + } + } else if (eType instanceof EEnum) { + if (jsonElement == null || jsonElement instanceof JsonNull) { + return null; + } + return jsonElement.getAsInt(); + } else if (eType instanceof EDataType) { + if (jsonElement == null || jsonElement instanceof JsonNull) { + return null; + } + EDataType eDataType = (EDataType)eType; + if (eDataType == EcorePackage.eINSTANCE.getEString()) { + return jsonElement.getAsString(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEBigDecimal()) { + return jsonElement.getAsBigDecimal(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEBigInteger()) { + return jsonElement.getAsBigInteger(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEBoolean()) { + return jsonElement.getAsBoolean(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEByte()) { + return jsonElement.getAsByte(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEChar()) { + return jsonElement.getAsCharacter(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEDate()) { + return new Date(jsonElement.getAsLong()); + } + else if (eDataType == EcorePackage.eINSTANCE.getEDouble()) { + return jsonElement.getAsDouble(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEFloat()) { + return jsonElement.getAsFloat(); + } + else if (eDataType == EcorePackage.eINSTANCE.getELong()) { + return jsonElement.getAsLong(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEInt()) { + return jsonElement.getAsInt(); + } + else if (eDataType == EcorePackage.eINSTANCE.getEIntegerObject()) { + return new Integer(jsonElement.getAsInt()); + } + else if (eDataType == EcorePackage.eINSTANCE.getEShort()) { + return jsonElement.getAsShort(); + } + return jsonElement.getAsString(); // for custom types + } + + return null; + } + +} diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/.classpath b/plugins/org.eclipse.emf.cdo.tests.couchbase/.classpath new file mode 100644 index 0000000000..64c5e31b7a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/.project b/plugins/org.eclipse.emf.cdo.tests.couchbase/.project new file mode 100644 index 0000000000..8b3af59638 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.emf.cdo.tests.couchbase</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.emf.cdo.tests.couchbase/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..af0f20f97a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/CDO AllTests (Couchbase).launch b/plugins/org.eclipse.emf.cdo.tests.couchbase/CDO AllTests (Couchbase).launch new file mode 100644 index 0000000000..07a1d7caac --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/CDO AllTests (Couchbase).launch @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsCouchbase.java"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="1"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emf.cdo.tests.couchbase.AllTestsCouchbase"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.emf.cdo.tests.couchbase"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:MaxPermSize=128m -Xmx1024m"/> +</launchConfiguration> diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/CDO AllTests (Couchbase-memcached).launch b/plugins/org.eclipse.emf.cdo.tests.couchbase/CDO AllTests (Couchbase-memcached).launch new file mode 100644 index 0000000000..bfaccd5bd7 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/CDO AllTests (Couchbase-memcached).launch @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsMemcached.java"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="1"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emf.cdo.tests.couchbase.AllTestsMemcached"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.emf.cdo.tests.couchbase"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:MaxPermSize=128m -Xmx1024m"/> +</launchConfiguration> diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.tests.couchbase/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..f8370f3285 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Couchbase Tests for CDO +Bundle-SymbolicName: org.eclipse.emf.cdo.tests.couchbase +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: eclipse.org +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Require-Bundle: org.eclipse.emf.cdo.tests;bundle-version="[4.0.0,5.0.0)", + org.eclipse.emf.cdo.server.couchbase;bundle-version="[1.0.0,2.0.0)", + com.couchbase.client;bundle-version="[1.1.5,2.0.0)", + org.apache.commons.codec;bundle-version="[1.5.0,2.0.0)", + net.spy.memcached;bundle-version="[2.8.0,3.0.0)", + com.google.gson;bundle-version="[2.2.0,3.0.0)" diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/build.properties b/plugins/org.eclipse.emf.cdo.tests.couchbase/build.properties new file mode 100644 index 0000000000..34d2e4d2da --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/hs_err_pid6840.log b/plugins/org.eclipse.emf.cdo.tests.couchbase/hs_err_pid6840.log new file mode 100644 index 0000000000..d82c8e029f --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/hs_err_pid6840.log @@ -0,0 +1,366 @@ +# +# A fatal error has been detected by the Java Runtime Environment: +# +# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006340df5b, pid=6840, tid=1880 +# +# JRE version: 7.0_21-b11 +# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.21-b01 mixed mode windows-amd64 compressed oops) +# Problematic frame: +# V [jvm.dll+0x11df5b] +# +# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows +# +# If you would like to submit a bug report, please visit: +# http://bugreport.sun.com/bugreport/crash.jsp +# + +--------------- T H R E A D --------------- + +Current thread (0x000000000b489000): JavaThread "JDWP Transport Listener: dt_socket" daemon [_thread_in_vm, id=1880, stack(0x000000000b1c0000,0x000000000b2c0000)] + +siginfo: ExceptionCode=0xc0000005, reading address 0x00003b6c616e7265 + +Registers: +RAX=0x000000000b2bf201, RBX=0x000000000b489000, RCX=0x00003b6c616e7265, RDX=0x000000000b489000 +RSP=0x000000000b2bf230, RBP=0x00003b6c616e7265, RSI=0x000000000b2bf348, RDI=0x0000000001deb1c0 +R8 =0x000000000b2bf348, R9 =0x0000ac470bae0121, R10=0x656a624f2f676e61, R11=0x000000000cee1999 +R12=0x0000000000000000, R13=0x0000000000000000, R14=0x0000000000000000, R15=0x0000000000000000 +RIP=0x000000006340df5b, EFLAGS=0x0000000000010206 + +Top of Stack: (sp=0x000000000b2bf230) +0x000000000b2bf230: 000000000b489000 0000000001f86840 +0x000000000b2bf240: 000000000b2bf2f8 0000000063595699 +0x000000000b2bf250: 000000000b489000 00000000635b1062 +0x000000000b2bf260: 0000000000000029 000000000b489000 +0x000000000b2bf270: 000000000cefcc70 00000000648d264e +0x000000000b2bf280: 000000000b489000 0000000000000000 +0x000000000b2bf290: 0000000000000000 0000000000000000 +0x000000000b2bf2a0: 00003b6c616e7265 00000000648d1745 +0x000000000b2bf2b0: 000000000b2bf348 000000000b2bf320 +0x000000000b2bf2c0: 0000000000000001 000000000cefcc70 +0x000000000b2bf2d0: 00003b6c616e7265 00000000648b53b3 +0x000000000b2bf2e0: 000000000b2bf410 0000000000000001 +0x000000000b2bf2f0: 0000000000000001 000000000cefcc70 +0x000000000b2bf300: 0000000000000009 0000000000000000 +0x000000000b2bf310: 0000000000000000 0000000000000000 +0x000000000b2bf320: 0000000000000001 00000000648b5571 + +Instructions: (pc=0x000000006340df5b) +0x000000006340df3b: 48 8b 5c 24 30 48 89 47 18 48 83 c4 20 5f c3 cc +0x000000006340df4b: cc cc cc cc cc 40 53 48 83 ec 20 48 85 c9 74 54 +0x000000006340df5b: 48 8b 19 48 85 db 74 4c 48 b8 fe fe fe fe fe fe +0x000000006340df6b: fe fe 48 3b d8 74 3d 80 3d ff fd 58 00 00 74 15 + + +Register to memory mapping: + +RAX=0x000000000b2bf201 is pointing into the stack for thread: 0x000000000b489000 +RBX=0x000000000b489000 is a thread +RCX=0x00003b6c616e7265 is an unknown value +RDX=0x000000000b489000 is a thread +RSP=0x000000000b2bf230 is pointing into the stack for thread: 0x000000000b489000 +RBP=0x00003b6c616e7265 is an unknown value +RSI=0x000000000b2bf348 is pointing into the stack for thread: 0x000000000b489000 +RDI=0x0000000001deb1c0 is an unknown value +R8 =0x000000000b2bf348 is pointing into the stack for thread: 0x000000000b489000 +R9 =0x0000ac470bae0121 is an unknown value +R10=0x656a624f2f676e61 is an unknown value +R11=0x000000000cee1999 is an unknown value +R12=0x0000000000000000 is an unknown value +R13=0x0000000000000000 is an unknown value +R14=0x0000000000000000 is an unknown value +R15=0x0000000000000000 is an unknown value + + +Stack: [0x000000000b1c0000,0x000000000b2c0000], sp=0x000000000b2bf230, free space=1020k +Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) +V [jvm.dll+0x11df5b] + + +--------------- P R O C E S S --------------- + +Java Threads: ( => current thread ) + 0x000000000de7b000 JavaThread "pool-13-thread-2" [_thread_blocked, id=7132, stack(0x00000000104f0000,0x00000000105f0000)] + 0x000000000de7a800 JavaThread "CDORevisionCacheCleaner-SignalProtocol[2, CLIENT, cdo]" daemon [_thread_blocked, id=3816, stack(0x00000000111e0000,0x00000000112e0000)] + 0x000000000de79800 JavaThread "net4j-Thread-3" daemon [_thread_blocked, id=2172, stack(0x0000000011070000,0x0000000011170000)] + 0x000000000de79000 JavaThread "Net4jReceiveSerializer-Channel[2, SERVER, cdo]" daemon [_thread_blocked, id=4952, stack(0x0000000010c00000,0x0000000010d00000)] + 0x000000000de77800 JavaThread "Net4jReceiveSerializer-Channel[2, CLIENT, cdo]" daemon [_thread_blocked, id=3792, stack(0x000000000e790000,0x000000000e890000)] + 0x000000000de78000 JavaThread "pool-13-thread-1" [_thread_blocked, id=6624, stack(0x000000000e520000,0x000000000e620000)] + 0x000000000de76800 JavaThread "monitor-timer" daemon [_thread_blocked, id=4452, stack(0x0000000010ed0000,0x0000000010fd0000)] + 0x000000000d0ba800 JavaThread "I/O dispatcher 8" [_thread_in_native, id=6524, stack(0x0000000010a50000,0x0000000010b50000)] + 0x000000000d0ba000 JavaThread "I/O dispatcher 7" [_thread_in_native, id=3596, stack(0x0000000010800000,0x0000000010900000)] + 0x000000000d0b9000 JavaThread "New I/O worker #49" [_thread_in_native, id=4532, stack(0x000000000f5d0000,0x000000000f6d0000)] + 0x000000000d0b7000 JavaThread "Couchbase View Thread for node 127.0.0.1/127.0.0.1:8092" [_thread_in_native, id=4212, stack(0x000000000fcc0000,0x000000000fdc0000)] + 0x000000000cf1a000 JavaThread "Memcached IO over {MemcachedConnection to 127.0.0.1/127.0.0.1:11210}" [_thread_in_native, id=516, stack(0x000000000fba0000,0x000000000fca0000)] + 0x000000000d0b6000 JavaThread "New I/O worker #33" [_thread_in_native, id=3544, stack(0x0000000010320000,0x0000000010420000)] + 0x000000000d0b5800 JavaThread "I/O dispatcher 6" [_thread_in_native, id=6692, stack(0x0000000010220000,0x0000000010320000)] + 0x000000000d0b4800 JavaThread "I/O dispatcher 5" [_thread_in_native, id=2952, stack(0x0000000010000000,0x0000000010100000)] + 0x000000000cf19800 JavaThread "Couchbase View Thread for node 127.0.0.1/127.0.0.1:8092" [_thread_in_native, id=6628, stack(0x000000000f820000,0x000000000f920000)] + 0x000000000cf15800 JavaThread "Memcached IO over {MemcachedConnection to 127.0.0.1/127.0.0.1:11210}" [_thread_in_native, id=4644, stack(0x000000000f4d0000,0x000000000f5d0000)] + 0x000000000cf18800 JavaThread "I/O dispatcher 4" [_thread_in_native, id=6640, stack(0x000000000fa50000,0x000000000fb50000)] + 0x000000000cf18000 JavaThread "I/O dispatcher 3" [_thread_in_native, id=6788, stack(0x000000000eca0000,0x000000000eda0000)] + 0x000000000cf17000 JavaThread "New I/O worker #17" [_thread_in_native, id=4396, stack(0x000000000f940000,0x000000000fa40000)] + 0x000000000cf15000 JavaThread "Couchbase View Thread for node 127.0.0.1/127.0.0.1:8092" [_thread_in_native, id=6564, stack(0x000000000f390000,0x000000000f490000)] + 0x000000000cf14000 JavaThread "Memcached IO over {MemcachedConnection to 127.0.0.1/127.0.0.1:11210}" [_thread_in_native, id=2860, stack(0x000000000f210000,0x000000000f310000)] + 0x000000000b6ff800 JavaThread "CDORevisionCacheCleaner-Repository[repo1]" daemon [_thread_blocked, id=2104, stack(0x000000000f110000,0x000000000f210000)] + 0x000000000d10f800 JavaThread "New I/O worker #1" [_thread_in_native, id=2872, stack(0x000000000c690000,0x000000000c790000)] + 0x000000000d700000 JavaThread "I/O dispatcher 2" [_thread_in_native, id=1668, stack(0x000000000efd0000,0x000000000f0d0000)] + 0x000000000d6ff800 JavaThread "I/O dispatcher 1" [_thread_in_native, id=6220, stack(0x000000000ede0000,0x000000000eee0000)] + 0x000000000d703800 JavaThread "Couchbase View Thread for node 127.0.0.1/127.0.0.1:8092" [_thread_in_native, id=6908, stack(0x000000000eba0000,0x000000000eca0000)] + 0x000000000de30800 JavaThread "Memcached IO over {MemcachedConnection to 127.0.0.1/127.0.0.1:11210}" [_thread_in_native, id=6724, stack(0x000000000e8b0000,0x000000000e9b0000)] + 0x000000000cf02800 JavaThread "Net4jBufferPoolMonitor" daemon [_thread_blocked, id=6884, stack(0x000000000e400000,0x000000000e500000)] + 0x000000000cea5800 JavaThread "EMF Reference Cleaner" daemon [_thread_blocked, id=3148, stack(0x000000000d200000,0x000000000d300000)] + 0x000000000b82f800 JavaThread "ReaderThread" [_thread_in_native, id=6436, stack(0x000000000d330000,0x000000000d430000)] + 0x000000000b4c1000 JavaThread "Service Thread" daemon [_thread_blocked, id=6240, stack(0x000000000c0c0000,0x000000000c1c0000)] + 0x000000000b4be000 JavaThread "C2 CompilerThread1" daemon [_thread_blocked, id=6888, stack(0x000000000c7b0000,0x000000000c8b0000)] + 0x000000000b4bc800 JavaThread "C2 CompilerThread0" daemon [_thread_blocked, id=5844, stack(0x000000000c570000,0x000000000c670000)] + 0x000000000b496800 JavaThread "JDWP Command Reader" daemon [_thread_in_native, id=4036, stack(0x000000000c450000,0x000000000c550000)] + 0x000000000b495800 JavaThread "JDWP Event Helper Thread" daemon [_thread_blocked, id=5676, stack(0x000000000bec0000,0x000000000bfc0000)] +=>0x000000000b489000 JavaThread "JDWP Transport Listener: dt_socket" daemon [_thread_in_vm, id=1880, stack(0x000000000b1c0000,0x000000000b2c0000)] + 0x000000000b481800 JavaThread "Attach Listener" daemon [_thread_blocked, id=4540, stack(0x000000000bab0000,0x000000000bbb0000)] + 0x000000000b481000 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=6488, stack(0x000000000b960000,0x000000000ba60000)] + 0x000000000924f000 JavaThread "Finalizer" daemon [_thread_blocked, id=3872, stack(0x000000000b330000,0x000000000b430000)] + 0x0000000009247000 JavaThread "Reference Handler" daemon [_thread_blocked, id=6568, stack(0x000000000b0c0000,0x000000000b1c0000)] + 0x0000000001f68000 JavaThread "main" [_thread_blocked, id=3784, stack(0x00000000020e0000,0x00000000021e0000)] + +Other Threads: + 0x000000000923b800 VMThread [stack: 0x000000000af10000,0x000000000b010000] [id=2552] + 0x000000000b510000 WatcherThread [stack: 0x000000000c8f0000,0x000000000c9f0000] [id=6092] + +VM state:not at safepoint (normal execution) + +VM Mutex/Monitor currently owned by a thread: None + +Heap + PSYoungGen total 57344K, used 38561K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 63% used [0x00000000eaab0000,0x00000000ec964c58,0x00000000edac0000) + from space 8128K, 87% used [0x00000000ee2b0000,0x00000000ee9a37c0,0x00000000eeaa0000) + to space 8128K, 0% used [0x00000000edac0000,0x00000000edac0000,0x00000000ee2b0000) + ParOldGen total 131008K, used 88K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0016010,0x00000000c7ff0000) + PSPermGen total 21824K, used 21684K [0x00000000b8000000, 0x00000000b9550000, 0x00000000c0000000) + object space 21824K, 99% used [0x00000000b8000000,0x00000000b952d188,0x00000000b9550000) + +Card table byte_map: [0x00000000051e0000,0x0000000005430000] byte_map_base: 0x0000000004c20000 + +Polling page: 0x0000000000200000 + +Code Cache [0x00000000021e0000, 0x0000000002450000, 0x00000000051e0000) + total_blobs=716 nmethods=340 adapters=334 free_code_cache=47818Kb largest_free_block=48928064 + +Compilation events (10 events): +Event: 145.535 Thread 0x000000000b4be000 363 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject::awaitNanos (158 bytes) +Event: 145.555 Thread 0x000000000b4be000 nmethod 363 0x0000000002334e90 code [0x00000000023350e0, 0x0000000002335d38] +Event: 173.350 Thread 0x000000000b4bc800 364 java.util.concurrent.locks.ReentrantLock$Sync::tryRelease (45 bytes) +Event: 173.351 Thread 0x000000000b4bc800 nmethod 364 0x00000000022f56d0 code [0x00000000022f5800, 0x00000000022f5898] +Event: 185.491 Thread 0x000000000b4be000 365 java.util.concurrent.locks.ReentrantLock$NonfairSync::tryAcquire (6 bytes) +Event: 185.493 Thread 0x000000000b4be000 nmethod 365 0x00000000022f7790 code [0x00000000022f78c0, 0x00000000022f7998] +Event: 192.785 Thread 0x000000000b4bc800 366 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject::unlinkCancelledWaiters (67 bytes) +Event: 192.787 Thread 0x000000000b4bc800 nmethod 366 0x00000000022f5150 code [0x00000000022f5280, 0x00000000022f5358] +Event: 195.415 Thread 0x000000000b4be000 367 ! java.util.concurrent.LinkedBlockingQueue::poll (134 bytes) +Event: 195.427 Thread 0x000000000b4be000 nmethod 367 0x000000000232e010 code [0x000000000232e1e0, 0x000000000232e980] + +GC Heap History (8 events): +Event: 1.188 GC heap before +{Heap before GC invocations=1 (full 0): + PSYoungGen total 57344K, used 49216K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 100% used [0x00000000eaab0000,0x00000000edac0000,0x00000000edac0000) + from space 8128K, 0% used [0x00000000ee2b0000,0x00000000ee2b0000,0x00000000eeaa0000) + to space 8128K, 0% used [0x00000000edac0000,0x00000000edac0000,0x00000000ee2b0000) + ParOldGen total 131008K, used 0K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0000000,0x00000000c7ff0000) + PSPermGen total 21248K, used 9993K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 47% used [0x00000000b8000000,0x00000000b89c2738,0x00000000b94c0000) +Event: 1.194 GC heap after +Heap after GC invocations=1 (full 0): + PSYoungGen total 57344K, used 6129K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 0% used [0x00000000eaab0000,0x00000000eaab0000,0x00000000edac0000) + from space 8128K, 75% used [0x00000000edac0000,0x00000000ee0bc408,0x00000000ee2b0000) + to space 8128K, 0% used [0x00000000ee2b0000,0x00000000ee2b0000,0x00000000eeaa0000) + ParOldGen total 131008K, used 8K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0002000,0x00000000c7ff0000) + PSPermGen total 21248K, used 9993K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 47% used [0x00000000b8000000,0x00000000b89c2738,0x00000000b94c0000) +} +Event: 1.913 GC heap before +{Heap before GC invocations=2 (full 0): + PSYoungGen total 57344K, used 55345K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 100% used [0x00000000eaab0000,0x00000000edac0000,0x00000000edac0000) + from space 8128K, 75% used [0x00000000edac0000,0x00000000ee0bc408,0x00000000ee2b0000) + to space 8128K, 0% used [0x00000000ee2b0000,0x00000000ee2b0000,0x00000000eeaa0000) + ParOldGen total 131008K, used 8K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0002000,0x00000000c7ff0000) + PSPermGen total 21248K, used 13153K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 61% used [0x00000000b8000000,0x00000000b8cd8540,0x00000000b94c0000) +Event: 1.917 GC heap after +Heap after GC invocations=2 (full 0): + PSYoungGen total 57344K, used 4402K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 0% used [0x00000000eaab0000,0x00000000eaab0000,0x00000000edac0000) + from space 8128K, 54% used [0x00000000ee2b0000,0x00000000ee6fc810,0x00000000eeaa0000) + to space 8128K, 0% used [0x00000000edac0000,0x00000000edac0000,0x00000000ee2b0000) + ParOldGen total 131008K, used 16K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0004000,0x00000000c7ff0000) + PSPermGen total 21248K, used 13153K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 61% used [0x00000000b8000000,0x00000000b8cd8540,0x00000000b94c0000) +} +Event: 5.878 GC heap before +{Heap before GC invocations=3 (full 0): + PSYoungGen total 57344K, used 53618K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 100% used [0x00000000eaab0000,0x00000000edac0000,0x00000000edac0000) + from space 8128K, 54% used [0x00000000ee2b0000,0x00000000ee6fc810,0x00000000eeaa0000) + to space 8128K, 0% used [0x00000000edac0000,0x00000000edac0000,0x00000000ee2b0000) + ParOldGen total 131008K, used 16K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0004000,0x00000000c7ff0000) + PSPermGen total 21248K, used 16101K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 75% used [0x00000000b8000000,0x00000000b8fb9698,0x00000000b94c0000) +Event: 5.891 GC heap after +Heap after GC invocations=3 (full 0): + PSYoungGen total 57344K, used 6079K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 0% used [0x00000000eaab0000,0x00000000eaab0000,0x00000000edac0000) + from space 8128K, 74% used [0x00000000edac0000,0x00000000ee0afe00,0x00000000ee2b0000) + to space 8128K, 0% used [0x00000000ee2b0000,0x00000000ee2b0000,0x00000000eeaa0000) + ParOldGen total 131008K, used 16K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0004000,0x00000000c7ff0000) + PSPermGen total 21248K, used 16101K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 75% used [0x00000000b8000000,0x00000000b8fb9698,0x00000000b94c0000) +} +Event: 6.779 GC heap before +{Heap before GC invocations=4 (full 0): + PSYoungGen total 57344K, used 55295K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 100% used [0x00000000eaab0000,0x00000000edac0000,0x00000000edac0000) + from space 8128K, 74% used [0x00000000edac0000,0x00000000ee0afe00,0x00000000ee2b0000) + to space 8128K, 0% used [0x00000000ee2b0000,0x00000000ee2b0000,0x00000000eeaa0000) + ParOldGen total 131008K, used 16K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0004000,0x00000000c7ff0000) + PSPermGen total 21248K, used 19681K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 92% used [0x00000000b8000000,0x00000000b9338578,0x00000000b94c0000) +Event: 6.786 GC heap after +Heap after GC invocations=4 (full 0): + PSYoungGen total 57344K, used 7117K [0x00000000eaab0000, 0x00000000eeaa0000, 0x0000000100000000) + eden space 49216K, 0% used [0x00000000eaab0000,0x00000000eaab0000,0x00000000edac0000) + from space 8128K, 87% used [0x00000000ee2b0000,0x00000000ee9a37c0,0x00000000eeaa0000) + to space 8128K, 0% used [0x00000000edac0000,0x00000000edac0000,0x00000000ee2b0000) + ParOldGen total 131008K, used 88K [0x00000000c0000000, 0x00000000c7ff0000, 0x00000000eaab0000) + object space 131008K, 0% used [0x00000000c0000000,0x00000000c0016010,0x00000000c7ff0000) + PSPermGen total 21248K, used 19681K [0x00000000b8000000, 0x00000000b94c0000, 0x00000000c0000000) + object space 21248K, 92% used [0x00000000b8000000,0x00000000b9338578,0x00000000b94c0000) +} + +Deoptimization events (10 events): +Event: 18.987 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 18.987 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd478 +Event: 18.988 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 18.992 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 18.993 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 18.993 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 18.994 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 18.995 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 18.995 Thread 0x000000000de76000 Uncommon trap -89 fr.pc 0x00000000022cd214 +Event: 22.234 Thread 0x000000000de79800 Uncommon trap -83 fr.pc 0x0000000002247288 + +Internal exceptions (10 events): +Event: 19.054 Thread 0x000000000de79800 Threw 0x00000000ebed1c10 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.055 Thread 0x000000000de79800 Threw 0x00000000ebeec580 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.056 Thread 0x000000000de79800 Threw 0x00000000ebf05e38 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.058 Thread 0x000000000de79800 Threw 0x00000000ebf1e948 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.114 Thread 0x000000000de79800 Threw 0x00000000ebf42148 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.129 Thread 0x0000000001f68000 Threw 0x00000000ebf878e8 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.130 Thread 0x0000000001f68000 Threw 0x00000000ebf950a8 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.131 Thread 0x0000000001f68000 Threw 0x00000000ebfa5f60 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 19.152 Thread 0x0000000001f68000 Threw 0x00000000ebfd0778 at C:\jdk7u2_64p\jdk7u21\hotspot\src\share\vm\prims\jvm.cpp:1166 +Event: 22.234 Thread 0x000000000de79800 Implicit null exception at 0x0000000002246e49 to 0x0000000002247271 + +Events (10 events): +Event: 226.998 Executing VM operation: GetCurrentLocation +Event: 226.998 Executing VM operation: GetCurrentLocation done +Event: 226.998 Executing VM operation: EnterInterpOnlyMode +Event: 226.998 Executing VM operation: EnterInterpOnlyMode done +Event: 226.998 Executing VM operation: ChangeSingleStep +Event: 226.998 Executing VM operation: ChangeSingleStep done +Event: 226.998 Executing VM operation: ChangeSingleStep +Event: 226.998 Executing VM operation: ChangeSingleStep done +Event: 227.006 Executing VM operation: RedefineClasses +Event: 227.009 Executing VM operation: RedefineClasses done + + +Dynamic libraries: +0x000000013ff00000 - 0x000000013ff33000 C:\Program Files\Java\jre7\bin\javaw.exe +0x00000000772d0000 - 0x0000000077479000 C:\Windows\SYSTEM32\ntdll.dll +0x00000000771b0000 - 0x00000000772cf000 C:\Windows\system32\kernel32.dll +0x000007fefd470000 - 0x000007fefd4db000 C:\Windows\system32\KERNELBASE.dll +0x000007feff250000 - 0x000007feff32b000 C:\Windows\system32\ADVAPI32.dll +0x000007fefddd0000 - 0x000007fefde6f000 C:\Windows\system32\msvcrt.dll +0x000007fefdb80000 - 0x000007fefdb9f000 C:\Windows\SYSTEM32\sechost.dll +0x000007fefde70000 - 0x000007fefdf9d000 C:\Windows\system32\RPCRT4.dll +0x00000000770b0000 - 0x00000000771aa000 C:\Windows\system32\USER32.dll +0x000007fefe450000 - 0x000007fefe4b7000 C:\Windows\system32\GDI32.dll +0x000007feff5d0000 - 0x000007feff5de000 C:\Windows\system32\LPK.dll +0x000007fefd8a0000 - 0x000007fefd969000 C:\Windows\system32\USP10.dll +0x000007fefbb60000 - 0x000007fefbd54000 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_fa396087175ac9ac\COMCTL32.dll +0x000007fefd4e0000 - 0x000007fefd551000 C:\Windows\system32\SHLWAPI.dll +0x000007fefe420000 - 0x000007fefe44e000 C:\Windows\system32\IMM32.DLL +0x000007fefe1b0000 - 0x000007fefe2b9000 C:\Windows\system32\MSCTF.dll +0x0000000063a20000 - 0x0000000063af1000 C:\Program Files\Java\jre7\bin\msvcr100.dll +0x00000000632f0000 - 0x0000000063a11000 C:\Program Files\Java\jre7\bin\server\jvm.dll +0x000007fef8780000 - 0x000007fef8789000 C:\Windows\system32\WSOCK32.dll +0x000007fefe100000 - 0x000007fefe14d000 C:\Windows\system32\WS2_32.dll +0x000007feff5c0000 - 0x000007feff5c8000 C:\Windows\system32\NSI.dll +0x000007fefac40000 - 0x000007fefac7b000 C:\Windows\system32\WINMM.dll +0x0000000077490000 - 0x0000000077497000 C:\Windows\system32\PSAPI.DLL +0x0000000074d50000 - 0x0000000074d5f000 C:\Program Files\Java\jre7\bin\verify.dll +0x00000000632c0000 - 0x00000000632e8000 C:\Program Files\Java\jre7\bin\java.dll +0x00000000648b0000 - 0x00000000648e5000 C:\Program Files\Java\jre7\bin\jdwp.dll +0x00000000648a0000 - 0x00000000648a8000 C:\Program Files\Java\jre7\bin\npt.dll +0x00000000632a0000 - 0x00000000632b5000 C:\Program Files\Java\jre7\bin\zip.dll +0x0000000064890000 - 0x0000000064899000 C:\Program Files\Java\jre7\bin\dt_socket.dll +0x000007fefa900000 - 0x000007fefa915000 C:\Windows\system32\NLAapi.dll +0x000007fef80a0000 - 0x000007fef80b5000 C:\Windows\system32\napinsp.dll +0x000007fef8080000 - 0x000007fef8099000 C:\Windows\system32\pnrpnsp.dll +0x000007fefc900000 - 0x000007fefc955000 C:\Windows\System32\mswsock.dll +0x000007fefc790000 - 0x000007fefc7eb000 C:\Windows\system32\DNSAPI.dll +0x000007fef8070000 - 0x000007fef807b000 C:\Windows\System32\winrnr.dll +0x000007fefa760000 - 0x000007fefa787000 C:\Windows\system32\IPHLPAPI.DLL +0x000007fefa750000 - 0x000007fefa75b000 C:\Windows\system32\WINNSI.DLL +0x000007fefa4e0000 - 0x000007fefa533000 C:\Windows\System32\fwpuclnt.dll +0x000007fef8060000 - 0x000007fef8068000 C:\Windows\system32\rasadhlp.dll +0x000007fefc2c0000 - 0x000007fefc2c7000 C:\Windows\System32\wshtcpip.dll +0x0000000068780000 - 0x0000000068799000 C:\Program Files\Java\jre7\bin\net.dll +0x000007fefcb80000 - 0x000007fefcb87000 C:\Windows\System32\wship6.dll +0x0000000063280000 - 0x0000000063291000 C:\Program Files\Java\jre7\bin\nio.dll +0x000007fefc960000 - 0x000007fefc977000 C:\Windows\system32\CRYPTSP.dll +0x000007fefc670000 - 0x000007fefc6b7000 C:\Windows\system32\rsaenh.dll +0x000007fefc3f0000 - 0x000007fefc40e000 C:\Windows\system32\USERENV.dll +0x000007fefd0b0000 - 0x000007fefd0bf000 C:\Windows\system32\profapi.dll +0x000007fefcfe0000 - 0x000007fefcfef000 C:\Windows\system32\CRYPTBASE.dll +0x0000000064860000 - 0x0000000064884000 C:\Program Files\Java\jre7\bin\sunec.dll +0x0000000064850000 - 0x000000006485b000 C:\Program Files\Java\jre7\bin\sunmscapi.dll +0x000007fefd1c0000 - 0x000007fefd32a000 C:\Windows\system32\CRYPT32.dll +0x000007fefd150000 - 0x000007fefd15f000 C:\Windows\system32\MSASN1.dll +0x000007fef8bc0000 - 0x000007fef8ce5000 C:\Windows\system32\dbghelp.dll + +VM Arguments: +jvm_args: -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:3250 -XX:MaxPermSize=128m -Xmx1024m -Dfile.encoding=UTF-8 +java_command: org.eclipse.jdt.internal.junit.runner.RemoteTestRunner -version 3 -port 3249 -testLoaderClass org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader -loaderpluginname org.eclipse.jdt.junit.runtime -test org.eclipse.emf.cdo.tests.ChunkingTest:testPartiallyLoadedAddAtIndex +Launcher Type: SUN_STANDARD + +Environment Variables: +PATH=C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\YourKit Java Profiler 12.0.2\bin\win64;C:\Program Files (x86)\Git\cmd;C:\Program Files (x86)\CVSNT\ +USERNAME=vroldan +OS=Windows_NT +PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 26 Stepping 5, GenuineIntel + + + +--------------- S Y S T E M --------------- + +OS: Windows 7 , 64 bit Build 7601 Service Pack 1 + +CPU:total 8 (4 cores per cpu, 2 threads per core) family 6 model 26 stepping 5, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, ht, tsc, tscinvbit, tscinv + +Memory: 4k page, physical 12573816k(7127872k free), swap 25145772k(16751756k free) + +vm_info: Java HotSpot(TM) 64-Bit Server VM (23.21-b01) for windows-amd64 JRE (1.7.0_21-b11), built on Apr 4 2013 08:11:28 by "java_re" with unknown MS VC++:1600 + +time: Mon Aug 05 11:42:14 2013 +elapsed time: 227 seconds + diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsCouchbase.java b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsCouchbase.java new file mode 100644 index 0000000000..cf20994191 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsCouchbase.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011-2013 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: + * Victor Roldan Betancort - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.couchbase; + +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.emf.cdo.tests.AllConfigs; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_261218_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_303466_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_324585_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_411927_Test; +import org.eclipse.emf.cdo.tests.config.IScenario; +import org.eclipse.emf.cdo.tests.config.impl.ConfigTest; + +import com.couchbase.client.clustermanager.BucketType; + +/** + * Some comments on setting up the tests: + * <p> + * check the server does have memory free for new bucket creation. + * If no memory is available, bucket creation fails silently + * <p> + * increase bucket number limit + * http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-admin-restapi-max-buckets.html + * curl -X POST -u admin:password -d maxBucketCount=20 http://ip_address:8091/internalSettings + * + * @author Victor Roldan Betancort + */ +public class AllTestsCouchbase extends AllConfigs +{ + public static Test suite() + { + return new AllTestsCouchbase().getTestSuite(); + } + + @Override + protected void initConfigSuites(TestSuite parent) + { + addScenario(parent, COMBINED, new CouchbaseConfig(BucketType.COUCHBASE), JVM, NATIVE); + } + + @Override + protected void initTestClasses(List<Class<? extends ConfigTest>> testClasses, IScenario scenario) + { + super.initTestClasses(testClasses, scenario); + + // Added here testcases to skip + // takes too much + testClasses.remove(Bugzilla_261218_Test.class); + testClasses.remove(Bugzilla_324585_Test.class); + testClasses.remove(Bugzilla_411927_Test.class); + + // this test-case uses files that cannot be found because + // are no longer where is expected (due to git) + // (if manually added the file, it passes) + testClasses.remove(Bugzilla_303466_Test.class); + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsMemcached.java b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsMemcached.java new file mode 100644 index 0000000000..9b44d8b69d --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/AllTestsMemcached.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011-2013 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: + * Victor Roldan Betancort - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.couchbase; + +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.emf.cdo.tests.AllConfigs; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_303466_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_324585_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_377212_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_390185_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_411927_Test; +import org.eclipse.emf.cdo.tests.config.IScenario; +import org.eclipse.emf.cdo.tests.config.impl.ConfigTest; + +import com.couchbase.client.clustermanager.BucketType; + +/** + * Some comments on setting up the tests: + * <p> + * check the server does have memory free for new bucket creation. + * If no memory is available, bucket creation fails silently + * <p> + * increase bucket number limit + * http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-admin-restapi-max-buckets.html + * curl -X POST -u admin:password -d maxBucketCount=20 http://ip_address:8091/internalSettings + * + * @author Victor Roldan Betancort + */ +public class AllTestsMemcached extends AllConfigs +{ + public static Test suite() + { + return new AllTestsMemcached().getTestSuite(); + } + + @Override + protected void initConfigSuites(TestSuite parent) + { + addScenario(parent, COMBINED, new CouchbaseConfig(BucketType.MEMCACHED), JVM, NATIVE); + } + + @Override + protected void initTestClasses(List<Class<? extends ConfigTest>> testClasses, IScenario scenario) + { + super.initTestClasses(testClasses, scenario); + + // Added here test-cases to skip + // takes too much + testClasses.remove(Bugzilla_324585_Test.class); // 33s + testClasses.remove(Bugzilla_377212_Test.class); // 36s + testClasses.remove(Bugzilla_390185_Test.class); // 30s + testClasses.remove(Bugzilla_411927_Test.class); // does not end + + // this test-case uses files that cannot be found because + // are no longer where is expected (due to git) + // (if manually added the file, it passes) + testClasses.remove(Bugzilla_303466_Test.class); + + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/CouchbaseConfig.java b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/CouchbaseConfig.java new file mode 100644 index 0000000000..c790750e6c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/CouchbaseConfig.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2011, 2013 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: + * Victor Roldan Betancort - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.couchbase; + +import java.net.URI; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation; +import org.eclipse.emf.cdo.server.IStore; +import org.eclipse.emf.cdo.server.couchbase.ICouchbaseStore; +import org.eclipse.emf.cdo.server.internal.CouchbaseStore; +import org.eclipse.emf.cdo.tests.config.impl.RepositoryConfig; + +import com.couchbase.client.clustermanager.BucketType; + +/** + * @author Victor Roldan Betancort + */ +public class CouchbaseConfig extends RepositoryConfig { + private static final long serialVersionUID = 1L; + + private static final String HOST = "localhost"; + + private static final String PORT = "8091"; + + private static final String USER = "Administrator"; + + private static final String PASS = "scaverok"; + + private static final URI COUCHBASE_URI = URI.create("http://" + HOST + ":" + PORT + "/pools"); + + private static Map<String, Boolean> bucketCleaned = new HashMap<String, Boolean>(); + + private static boolean firstRun = true; + + private transient CouchbaseUtil couchbaseUtil; + + private BucketType bucketType; + + public CouchbaseConfig(BucketType bucketType) { + super(ICouchbaseStore.TYPE, false, false, IDGenerationLocation.STORE); + this.bucketType = bucketType; + } + + @Override + public void initCapabilities(Set<String> capabilities) { + super.initCapabilities(capabilities); + } + + @Override + protected String getStoreName() { + return "Couchbase"; + } + + public IStore createStore(String repoName) { + initBucket(repoName); + List<URI> uris = new LinkedList<URI>(); + uris.add(COUCHBASE_URI); + return new CouchbaseStore(uris, repoName, USER, PASS); + } + + // buckets get cleaned only once for the whole test-suite + // (cleaning takes too much) + private void initBucket(String repoName) { + if (firstRun) { + try { + getCouchbaseUtil().deleteAllBuckets(); + } catch (Exception e) { + e.printStackTrace(); + } + firstRun = false; + } + Boolean bucketIsClean = bucketCleaned.get(repoName); + if (bucketIsClean == null) { + bucketIsClean = false; + } + if (!bucketIsClean || needsCleanRepos()) { + try { + getCouchbaseUtil().cleanBucket(repoName); + bucketCleaned.put(repoName, true); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private CouchbaseUtil getCouchbaseUtil() { + if (couchbaseUtil == null) { + couchbaseUtil = new CouchbaseUtil(bucketType, HOST, PORT, USER, PASS); + } + return couchbaseUtil; + } + + + @Override + protected void deactivateRepositories() { + super.deactivateRepositories(); + if (couchbaseUtil != null) { + couchbaseUtil.clear(); + } + couchbaseUtil = null; + } + + +} diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/CouchbaseUtil.java b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/CouchbaseUtil.java new file mode 100644 index 0000000000..0fc5263200 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/CouchbaseUtil.java @@ -0,0 +1,176 @@ +package org.eclipse.emf.cdo.tests.couchbase; + +import java.io.IOException; +import java.net.SocketAddress; +import java.net.URI; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; + +import net.spy.memcached.MemcachedClient; + +import com.couchbase.client.ClusterManager; +import com.couchbase.client.CouchbaseClient; +import com.couchbase.client.CouchbaseConnectionFactory; +import com.couchbase.client.CouchbaseConnectionFactoryBuilder; +import com.couchbase.client.clustermanager.BucketType; + +public class CouchbaseUtil { + + private static final int BUCKET_MEMORY = 100; + + private ClusterManager manager; + + private MemcachedClient client; + + private BucketType bucketType; + + private String host; + + private String port; + + private String user; + + private String pass; + + public CouchbaseUtil(BucketType bucketType, String host, String port, String user, String pass) { + this.bucketType = bucketType; + this.host = host; + this.port = port; + this.user = user; + this.pass = pass; + } + + public boolean isBucketEmpty(String bucketName) { + Map<SocketAddress, Map<String, String>> stats = getClient(bucketName) + .getStats(); + for (Entry<SocketAddress, Map<String, String>> server : stats + .entrySet()) { + Map<String, String> serverStats = server.getValue(); + if (bucketName.equals(serverStats.get("ep_couch_bucket"))) { + String value = serverStats.get("curr_items"); + if (value != null) { + if (Integer.parseInt(value) == 0) { + return true; + } else { + return false; + } + } + } + } + return false; + } + + /* + * Makes sure the argument bucket is created and empty + */ + public void cleanBucket(String bucketName) throws Exception { + if (!existBucket(bucketName)) { + try { + createBucket(bucketName); + // it is necessary to wait a bit after creation or client connection will fail + // see http://www.couchbase.com/forums/thread/number-buckets-must-be-power-two-0-and-0 + if (bucketType == BucketType.COUCHBASE) { + Thread.sleep(1000); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + if (!isBucketEmpty(bucketName)) { + flushBucket(bucketName); + } + + } + waitForWarmup(bucketName); + } + + public void createBucket(String bucketName) throws Exception { + ClusterManager manager = getClusterManager(); + manager.createNamedBucket(bucketType, bucketName, BUCKET_MEMORY, 0, pass, true); + } + + public void flushBucket(String bucketName) { + ClusterManager manager = getClusterManager(); + manager.flushBucket(bucketName); + } + + public void deleteBucket(String bucketName) throws Exception { + ClusterManager manager = getClusterManager(); + manager.deleteBucket(bucketName); + } + + public void deleteAllBuckets() throws Exception { + ClusterManager manager = getClusterManager(); + for (String bucketName : manager.listBuckets()) { + manager.deleteBucket(bucketName); + } + } + + public boolean existBucket(String bucketName) throws Exception { + ClusterManager manager = getClusterManager(); + return manager.listBuckets().contains(bucketName); + } + + public ClusterManager getClusterManager() { + if (manager == null) { + List<URI> uris = new LinkedList<URI>(); + uris.add(URI.create("http://" + host + ":" + port + "/pools")); + manager = new ClusterManager(uris, user, pass); + } + return manager; + } + + public MemcachedClient getClient(String bucketName) { + if (client == null) { + List<URI> uris = new LinkedList<URI>(); + uris.add(URI.create("http://" + host + ":" + port + "/pools")); + try { + CouchbaseConnectionFactoryBuilder connectionFactoryBuilder = new CouchbaseConnectionFactoryBuilder(); + connectionFactoryBuilder.setOpTimeout(10000); // To avoid random "Cancelled" upon client.get() calls + CouchbaseConnectionFactory connectionFactory = connectionFactoryBuilder.buildCouchbaseConnection(uris, bucketName, user, pass); + client = new CouchbaseClient((CouchbaseConnectionFactory)connectionFactory); + } catch (IOException e) { + e.printStackTrace(); + } + } + return client; + } + + public void waitForWarmup(String bucketName) throws Exception { + // Couchbase-type bucket needs warmup time after flush, memcached does not + boolean warmup = bucketType == BucketType.COUCHBASE? true : false; + while (warmup) { + warmup = false; + Map<SocketAddress, Map<String, String>> stats = getClient( + bucketName).getStats(); + for (Entry<SocketAddress, Map<String, String>> server : stats + .entrySet()) { + Map<String, String> serverStats = server.getValue(); + if (!serverStats.containsKey("ep_degraded_mode")) { + warmup = true; + Thread.sleep(1000); + break; + } + if (!serverStats.get("ep_degraded_mode").equals("0")) { + warmup = true; + Thread.sleep(1000); + break; + } + } + } + } + + public void clear() { + if (client != null) { + client.shutdown(10, TimeUnit.SECONDS); + client = null; + } + if (manager != null) { + manager.shutdown(); + manager = null; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/bundle/OM.java b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/bundle/OM.java new file mode 100644 index 0000000000..09cdf4c322 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.couchbase/src/org/eclipse/emf/cdo/tests/couchbase/bundle/OM.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009, 2011, 2013 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: + * Victor Roldan Betancort - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.couchbase.bundle; + +import org.eclipse.net4j.util.om.OMBundle; +import org.eclipse.net4j.util.om.OMPlatform; +import org.eclipse.net4j.util.om.OSGiActivator; +import org.eclipse.net4j.util.om.log.OMLogger; +import org.eclipse.net4j.util.om.trace.OMTracer; + +/** + * The <em>Operations & Maintenance</em> class of this bundle. + * + * @author Victor Roldan Betancort + */ +public abstract class OM +{ + public static final String BUNDLE_ID = "org.eclipse.emf.cdo.tests.couchbase"; //$NON-NLS-1$ + + public static final OMBundle BUNDLE = OMPlatform.INSTANCE.bundle(BUNDLE_ID, OM.class); + + public static final OMTracer DEBUG = BUNDLE.tracer("debug"); //$NON-NLS-1$ + + public static final OMLogger LOG = BUNDLE.logger(); + + /** + * @author Victor Roldan Betancort + */ + public static final class Activator extends OSGiActivator + { + public Activator() + { + super(BUNDLE); + } + } +} |