--- /dev/null
+package org.simantics.acorn.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+import org.simantics.acorn.ClusterManager;
+import org.simantics.db.Session;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.impl.ClusterBase;
+import org.simantics.db.impl.ClusterI;
+import org.simantics.db.impl.ClusterSupport;
+import org.simantics.db.impl.IClusterTable;
+import org.simantics.db.service.ClusterUID;
+
+import gnu.trove.map.hash.TIntObjectHashMap;
+
+public class ClusterSupport2 implements ClusterSupport, IClusterTable {
+
+ final private static boolean DEBUG = false;
+
+ public ClusterManager impl;
+
+ public TIntObjectHashMap<ClusterUID> uidCache = new TIntObjectHashMap<ClusterUID>();
+
+ public ClusterSupport2(ClusterManager impl) {
+ this.impl = impl;
+ }
+
+ @Override
+ public int createClusterKeyByClusterUID(ClusterUID clusterUID, long clusterId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ClusterBase getClusterByClusterUIDOrMake(ClusterUID clusterUID) {
+ try {
+ return impl.getClusterByClusterUIDOrMake(clusterUID);
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public ClusterBase getClusterByClusterId(long clusterId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ClusterBase getClusterByClusterKey(int clusterKey) {
+ throw new UnsupportedOperationException();
+ }
+
+ ReentrantReadWriteLock uidLock = new ReentrantReadWriteLock();
+ ReadLock uidRead = uidLock.readLock();
+ WriteLock uidWrite = uidLock.writeLock();
+
+ @Override
+ public ClusterUID getClusterUIDByResourceKey(int resourceKey) throws DatabaseException {
+
+ ClusterUID cuid;
+
+ uidRead.lock();
+ cuid = uidCache.get(resourceKey >> 12);
+ uidRead.unlock();
+ if(cuid != null) return cuid;
+ uidWrite.lock();
+ cuid = uidCache.get(resourceKey >> 12);
+ if(cuid == null) {
+ cuid = impl.getClusterUIDByResourceKeyWithoutMutex(resourceKey);
+ uidCache.put(resourceKey >> 12, cuid);
+ }
+ uidWrite.unlock();
+
+ return cuid;
+
+ }
+
+ @Override
+ public int getClusterKeyByClusterUIDOrMake(ClusterUID clusterUID) {
+ return impl.getClusterKeyByClusterUIDOrMakeWithoutMutex(clusterUID);
+ }
+
+ @Override
+ public int getClusterKeyByClusterUIDOrMake(long id1, long id2) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ClusterBase getClusterByResourceKey(int resourceKey) {
+ throw new UnsupportedOperationException();
+// return impl.getClusterByResourceKey(resourceKey);
+ }
+
+ @Override
+ public long getClusterIdOrCreate(ClusterUID clusterUID) {
+ return impl.getClusterIdOrCreate(clusterUID);
+ }
+
+ @Override
+ public void addStatement(Object cluster) {
+ // nop
+ }
+
+ @Override
+ public void cancelStatement(Object cluster) {
+ // nop
+ }
+
+ @Override
+ public void removeStatement(Object cluster) {
+ // nop
+ }
+
+ @Override
+ public void removeValue(Object cluster) {
+ // nop
+ }
+
+ @Override
+ public void setImmutable(Object cluster, boolean immutable) {
+ // nop
+ }
+
+ @Override
+ public void setDeleted(Object cluster, boolean deleted) {
+ // TODO Auto-generated method stub
+
+ }
+
+
+
+ @Override
+ public void cancelValue(Object cluster) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setValue(Object cluster, long clusterId, byte[] bytes,
+ int length) {
+ // nop
+ }
+
+ @Override
+ public void modiValue(Object _cluster, long clusterId, long voffset,
+ int length, byte[] bytes, int offset) {
+ // nop
+ }
+
+ @Override
+ public void createResource(Object cluster, short resourceIndex,
+ long clusterId) {
+ // No op
+ }
+
+ @Override
+ public void addStatementIndex(Object cluster, int resourceKey,
+ ClusterUID clusterUID, byte op) {
+ // No op
+ }
+
+ @Override
+ public void setStreamOff(boolean setOff) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean getStreamOff() {
+ return true;
+ }
+
+
+ private static class ResourceSegment {
+ public long valueSize;
+
+ public byte[] bytes;
+
+ ResourceSegment(long valueSize, byte[] bytes) {
+ this.valueSize = valueSize;
+ this.bytes = bytes;
+ }
+ }
+
+ public ResourceSegment getResourceSegment(int resourceIndex, ClusterUID clusterUID, long offset, short size)
+ throws DatabaseException {
+ if (DEBUG)
+ System.out.println("DEBUG: getResourceSegment ri=" + resourceIndex + " cid=" + clusterUID + " offset=" + offset + " size=" + size);
+
+ org.simantics.db.Database.Session.ResourceSegment t = impl.getResourceSegment(clusterUID.asBytes(), resourceIndex, offset, size);
+ return new ResourceSegment(t.getValueSize(), t.getSegment());
+
+ }
+
+ protected byte[] getValueBig(ClusterBase cluster, int resourceIndex, int offset, int length) throws DatabaseException {
+
+ assert(offset == 0);
+ assert(length == 0);
+
+ ClusterUID clusterUID = cluster.clusterUID;
+
+ return impl.getResourceFile(clusterUID.asBytes(), resourceIndex);
+
+ }
+
+ protected InputStream getValueStreamBig(ClusterBase cluster, final int resourceIndex, int offset, int length) throws DatabaseException {
+
+ final ClusterUID clusterUID = cluster.clusterUID;
+
+ if (DEBUG)
+ System.out.println("DEBUG: getResourceFile ri=" + resourceIndex + " cid=" + clusterUID + " off=" + offset + " len=" + length);
+ final int IMAX = 0xFFFF;
+ short slen = (short)Math.min(length != 0 ? length : IMAX, IMAX);
+ final ResourceSegment s = getResourceSegment(resourceIndex, clusterUID, offset, slen);
+ if (s.valueSize < 0)
+ throw new DatabaseException("Failed to get value for resource index=" + resourceIndex +
+ " cluster=" + clusterUID + " off=" + offset + " len=" + length + " (1).");
+ int ilen = (int)slen & 0xFFFF;
+ assert(s.bytes.length <= ilen);
+ if (0 == length) {
+ if (s.valueSize > Integer.MAX_VALUE)
+ throw new DatabaseException("Failed to get value for resource index=" + resourceIndex +
+ " cluster=" + clusterUID + " off=" + offset + " len=" + length +
+ ". Value size=" + s.valueSize + " (2).");
+ length = (int)s.valueSize;
+ }
+ long rSize = s.valueSize - offset;
+ if (rSize < length)
+ throw new DatabaseException("Failed to get value for resource index=" + resourceIndex +
+ " cluster=" + clusterUID + " off=" + offset + " len=" + length +
+ ". Value size=" + s.valueSize + " (3).");
+ else if (length <= IMAX)
+ return new ByteArrayInputStream(s.bytes);
+
+ final int finalLength = length;
+
+ return new InputStream() {
+
+ int left = finalLength;
+ long valueOffset = 0;
+ int offset = 0;
+ ResourceSegment _s = s;
+
+ @Override
+ public int read() throws IOException {
+
+ if(left <= 0) throw new IllegalStateException();
+
+ if(offset == _s.bytes.length) {
+ short slen = (short)Math.min(left, IMAX);
+ valueOffset += _s.bytes.length;
+ try {
+ _s = getResourceSegment(resourceIndex, clusterUID, valueOffset, slen);
+ } catch (DatabaseException e) {
+ throw new IOException(e);
+ }
+ offset = 0;
+ }
+
+ left--;
+ int result = _s.bytes[offset++];
+ if(result < 0) result += 256;
+ return result;
+
+ }
+
+ };
+
+ }
+
+ @Override
+ public InputStream getValueStreamEx(int resourceIndex, long clusterId)
+ throws DatabaseException {
+ ClusterBase cluster = impl.getClusterByClusterUIDOrMakeProxy(ClusterUID.make(0, clusterId));
+ return getValueStreamBig(cluster, resourceIndex, 0, 0);
+ }
+
+ @Override
+ public byte[] getValueEx(int resourceIndex, long clusterId)
+ throws DatabaseException {
+ ClusterBase cluster = impl.getClusterByClusterUIDOrMakeProxy(ClusterUID.make(0, clusterId));
+ return getValueBig(cluster, resourceIndex, 0, 0);
+ }
+
+ @Override
+ public byte[] getValueEx(int resourceIndex, long clusterId, long voffset,
+ int length) throws DatabaseException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getValueSizeEx(int resourceIndex, long clusterId)
+ throws DatabaseException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int wait4RequestsLess(int limit) throws DatabaseException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Session getSession() {
+ return null;
+ }
+
+ @Override
+ public IClusterTable getClusterTable() {
+ return this;
+ }
+
+ @Override
+ public <T extends ClusterI> T getClusterByClusterUIDOrMakeProxy(ClusterUID clusterUID) {
+ try {
+ return (T)impl.getClusterByClusterUIDOrMakeProxy(clusterUID);
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public <T extends ClusterI> T getClusterProxyByResourceKey(int resourceKey) {
+ try {
+ return impl.getClusterProxyByResourceKey(resourceKey);
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public int getClusterKeyByUID(long id1, long id2) throws DatabaseException {
+ return impl.getClusterKeyByUID(id1, id2);
+ }
+
+}