]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.acorn/src/org/simantics/acorn/internal/ClusterSupport2.java
Merge commit 'bf75fd9'
[simantics/platform.git] / bundles / org.simantics.acorn / src / org / simantics / acorn / internal / ClusterSupport2.java
1 package org.simantics.acorn.internal;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.util.concurrent.locks.ReentrantReadWriteLock;
7 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
8 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
9
10 import org.simantics.acorn.ClusterManager;
11 import org.simantics.acorn.exception.AcornAccessVerificationException;
12 import org.simantics.acorn.exception.IllegalAcornStateException;
13 import org.simantics.db.Session;
14 import org.simantics.db.exception.DatabaseException;
15 import org.simantics.db.impl.ClusterBase;
16 import org.simantics.db.impl.ClusterI;
17 import org.simantics.db.impl.ClusterSupport;
18 import org.simantics.db.impl.IClusterTable;
19 import org.simantics.db.service.ClusterUID;
20
21 import gnu.trove.map.hash.TIntObjectHashMap;
22
23 public class ClusterSupport2 implements ClusterSupport, IClusterTable {
24         
25         final private static boolean DEBUG = false;
26
27         public ClusterManager impl;
28         
29         public TIntObjectHashMap<ClusterUID> uidCache = new TIntObjectHashMap<ClusterUID>(); 
30         
31         public ClusterSupport2(ClusterManager impl) {
32                 this.impl = impl;
33         }
34         
35         @Override
36         public int createClusterKeyByClusterUID(ClusterUID clusterUID, long clusterId) {
37                 throw new UnsupportedOperationException();
38         }
39
40         @Override
41         public ClusterBase getClusterByClusterUIDOrMake(ClusterUID clusterUID) {
42                 try {
43             return impl.getClusterByClusterUIDOrMake(clusterUID);
44         } catch (DatabaseException e) {
45             e.printStackTrace();
46             return null;
47         }
48         }
49
50         @Override
51         public ClusterBase getClusterByClusterId(long clusterId) {
52                 throw new UnsupportedOperationException();
53         }
54
55         @Override
56         public ClusterBase getClusterByClusterKey(int clusterKey) {
57                 throw new UnsupportedOperationException();
58         }
59
60         ReentrantReadWriteLock uidLock = new ReentrantReadWriteLock();
61         ReadLock uidRead = uidLock.readLock();
62         WriteLock uidWrite = uidLock.writeLock();
63         
64         @Override
65         public ClusterUID getClusterUIDByResourceKey(int resourceKey) throws DatabaseException {
66
67                 ClusterUID cuid;
68                 
69                 uidRead.lock();
70                 cuid = uidCache.get(resourceKey >> 12);
71                 uidRead.unlock();
72                 if(cuid != null) return cuid;
73                 uidWrite.lock();
74                 cuid = uidCache.get(resourceKey >> 12);
75                 if(cuid == null) {
76                         cuid = impl.getClusterUIDByResourceKeyWithoutMutex(resourceKey); 
77                         uidCache.put(resourceKey >> 12, cuid);
78                 }
79                 uidWrite.unlock();
80                 
81                 return cuid;
82                 
83         }
84         
85         @Override
86         public int getClusterKeyByClusterUIDOrMake(ClusterUID clusterUID) {
87                 try {
88             return impl.getClusterKeyByClusterUIDOrMakeWithoutMutex(clusterUID);
89         } catch (IllegalAcornStateException | AcornAccessVerificationException e) {
90             throw new RuntimeException(e);
91         }
92         }
93         
94     @Override
95     public int getClusterKeyByClusterUIDOrMake(long id1, long id2) {
96                 throw new UnsupportedOperationException();
97     }
98
99         @Override
100         public ClusterBase getClusterByResourceKey(int resourceKey) {
101                 throw new UnsupportedOperationException();
102 //              return impl.getClusterByResourceKey(resourceKey);
103         }
104
105         @Override
106         public long getClusterIdOrCreate(ClusterUID clusterUID) {
107                 return impl.getClusterIdOrCreate(clusterUID);
108         }
109
110         @Override
111         public void addStatement(Object cluster) {
112                 // nop
113         }
114
115         @Override
116         public void cancelStatement(Object cluster) {
117                 // nop
118         }
119
120         @Override
121         public void removeStatement(Object cluster) {
122                 // nop
123         }
124
125         @Override
126         public void removeValue(Object cluster) {
127                 // nop
128         }
129
130         @Override
131         public void setImmutable(Object cluster, boolean immutable) {
132                 // nop
133         }
134
135         @Override
136         public void setDeleted(Object cluster, boolean deleted) {
137                 // TODO Auto-generated method stub
138                 
139         }
140
141         
142         
143         @Override
144         public void cancelValue(Object cluster) {
145                 throw new UnsupportedOperationException();
146         }
147
148         @Override
149         public void setValue(Object cluster, long clusterId, byte[] bytes,
150                         int length) {
151                 // nop
152         }
153
154         @Override
155         public void modiValue(Object _cluster, long clusterId, long voffset,
156                         int length, byte[] bytes, int offset) {
157                 // nop
158         }
159
160         @Override
161         public void createResource(Object cluster, short resourceIndex,
162                         long clusterId) {
163                 // No op
164         }
165
166         @Override
167         public void addStatementIndex(Object cluster, int resourceKey,
168                         ClusterUID clusterUID, byte op) {
169                 // No op
170         }
171
172         @Override
173         public void setStreamOff(boolean setOff) {
174                 throw new UnsupportedOperationException();
175         }
176
177         @Override
178         public boolean getStreamOff() {
179                 return true;
180         }
181
182         
183     private static class ResourceSegment {
184         public long   valueSize;
185
186         public byte[] bytes;
187
188         ResourceSegment(long valueSize, byte[] bytes) {
189             this.valueSize = valueSize;
190             this.bytes = bytes;
191         }
192     }
193
194     public ResourceSegment getResourceSegment(int resourceIndex, ClusterUID clusterUID, long offset, short size) throws DatabaseException {
195         if (DEBUG)
196             System.out.println("DEBUG: getResourceSegment ri=" + resourceIndex + " cid=" + clusterUID + " offset=" + offset + " size=" + size);
197         
198         try {
199             org.simantics.db.Database.Session.ResourceSegment t = impl.getResourceSegment(clusterUID.asBytes(), resourceIndex, offset, size);
200             return new ResourceSegment(t.getValueSize(), t.getSegment());
201         } catch (AcornAccessVerificationException | IllegalAcornStateException e) {
202             throw new DatabaseException(e);
203         }
204     }
205     
206     protected byte[] getValueBig(ClusterBase cluster, int resourceIndex, int offset, int length) throws DatabaseException {
207     
208         assert(offset == 0);
209         assert(length == 0);
210         
211         ClusterUID clusterUID = cluster.clusterUID;
212         
213         try {
214             return impl.getResourceFile(clusterUID.asBytes(), resourceIndex);
215         } catch (AcornAccessVerificationException | IllegalAcornStateException e) {
216             throw new DatabaseException(e);
217         }
218     }
219
220     protected InputStream getValueStreamBig(ClusterBase cluster, final int resourceIndex, int offset, int length) throws DatabaseException {
221
222         final ClusterUID clusterUID = cluster.clusterUID;
223         
224         if (DEBUG)
225                 System.out.println("DEBUG: getResourceFile ri=" + resourceIndex + " cid=" + clusterUID + " off=" + offset + " len=" + length);
226         final int IMAX = 0xFFFF;
227         short slen = (short)Math.min(length != 0 ? length : IMAX, IMAX);
228         final ResourceSegment s = getResourceSegment(resourceIndex, clusterUID, offset, slen);
229         if (s.valueSize < 0)
230                 throw new DatabaseException("Failed to get value for resource index=" + resourceIndex +
231                                 " cluster=" + clusterUID + " off=" + offset + " len=" + length + " (1).");
232         int ilen = (int)slen & 0xFFFF;
233         assert(s.bytes.length <= ilen);
234         if (0 == length) {
235                 if (s.valueSize > Integer.MAX_VALUE)
236                         throw new DatabaseException("Failed to get value for resource index=" + resourceIndex +
237                                         " cluster=" + clusterUID + " off=" + offset + " len=" + length +
238                                         ". Value size=" + s.valueSize + " (2).");
239                 length = (int)s.valueSize;
240         }
241         long rSize = s.valueSize - offset;
242         if (rSize < length)
243                 throw new DatabaseException("Failed to get value for resource index=" + resourceIndex +
244                                 " cluster=" + clusterUID + " off=" + offset + " len=" + length +
245                                 ". Value size=" + s.valueSize + " (3).");
246         else if (length <= IMAX)
247                 return new ByteArrayInputStream(s.bytes);
248
249         final int finalLength = length;
250
251         return new InputStream() {
252
253                 int left = finalLength;
254                 long valueOffset = 0;
255                 int offset = 0;
256                 ResourceSegment _s = s;
257
258                 @Override
259                 public int read() throws IOException {
260
261                         if(left <= 0)
262                             throw new IOException("left <= 0 for " + _s);
263
264                         if(offset == _s.bytes.length) {
265                                 short slen = (short)Math.min(left, IMAX);
266                                 valueOffset += _s.bytes.length;
267                                 try {
268                                         _s = getResourceSegment(resourceIndex, clusterUID, valueOffset, slen);
269                                 } catch (DatabaseException e) {
270                                         throw new IOException(e);
271                                 }
272                                 offset = 0;
273                         }
274
275                         left--;
276                         int result = _s.bytes[offset++];
277                         if(result < 0) result += 256;
278                         return result;
279
280                 }
281
282         };
283
284     }
285         
286         @Override
287         public InputStream getValueStreamEx(int resourceIndex, long clusterId)
288                         throws DatabaseException {
289                 ClusterBase cluster = impl.getClusterByClusterUIDOrMakeProxy(ClusterUID.make(0, clusterId));
290                 return getValueStreamBig(cluster, resourceIndex, 0, 0);
291         }
292
293         @Override
294         public byte[] getValueEx(int resourceIndex, long clusterId)
295                         throws DatabaseException {
296                 ClusterBase cluster = impl.getClusterByClusterUIDOrMakeProxy(ClusterUID.make(0, clusterId));
297                 return getValueBig(cluster, resourceIndex, 0, 0);
298         }
299
300         @Override
301         public byte[] getValueEx(int resourceIndex, long clusterId, long voffset,
302                         int length) throws DatabaseException {
303                 throw new UnsupportedOperationException();
304         }
305
306         @Override
307         public long getValueSizeEx(int resourceIndex, long clusterId)
308                         throws DatabaseException {
309                 throw new UnsupportedOperationException();
310         }
311
312         @Override
313         public int wait4RequestsLess(int limit) throws DatabaseException {
314                 throw new UnsupportedOperationException();
315         }
316
317         @Override
318         public Session getSession() {
319                 return null;
320         }
321
322         @Override
323         public IClusterTable getClusterTable() {
324                 return this;
325         }
326
327         @Override
328         public <T extends ClusterI> T getClusterByClusterUIDOrMakeProxy(ClusterUID clusterUID) {
329                 try {
330             return (T)impl.getClusterByClusterUIDOrMakeProxy(clusterUID);
331         } catch (DatabaseException e) {
332             e.printStackTrace();
333             return null;
334         }
335         }
336
337         @Override
338         public <T extends ClusterI> T getClusterProxyByResourceKey(int resourceKey) {
339                 try {
340             return impl.getClusterProxyByResourceKey(resourceKey);
341         } catch (DatabaseException e) {
342             e.printStackTrace();
343             return null;
344         }
345         }
346
347         @Override
348         public int getClusterKeyByUID(long id1, long id2) throws DatabaseException {
349                 return impl.getClusterKeyByUID(id1, id2);
350         }
351
352 }