]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterTable.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / ClusterTable.java
index c6fd11c4eb35900763e1176b51fe90f7001819e3..efb644acd78330df99bd86c305a1d21e73646ea7 100644 (file)
@@ -27,7 +27,6 @@ import org.simantics.db.Database;
 import org.simantics.db.Database.Session.ClusterChanges;
 import org.simantics.db.DevelopmentKeys;
 import org.simantics.db.SessionVariables;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.ClusterDoesNotExistException;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ResourceNotFoundException;
@@ -48,6 +47,7 @@ import org.simantics.db.service.ClusterCollectorPolicy;
 import org.simantics.db.service.ClusterCollectorPolicy.CollectorCluster;
 import org.simantics.db.service.ClusterUID;
 import org.simantics.utils.Development;
+import org.slf4j.LoggerFactory;
 
 import fi.vtt.simantics.procore.DebugPolicy;
 import fi.vtt.simantics.procore.internal.ClusterControlImpl.ClusterStateImpl;
@@ -61,6 +61,8 @@ import gnu.trove.set.hash.TIntHashSet;
 
 public final class ClusterTable implements IClusterTable {
 
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ClusterTable.class);
+    
     private static final boolean VALIDATE_SIZE = false;
 
     int maximumBytes = 128 * 1024 * 1024;
@@ -135,7 +137,7 @@ public final class ClusterTable implements IClusterTable {
             int clusterKey = hashMap.size();
             ClusterSmall sentinel = new ClusterSmall(clusterUID, clusterKey, ClusterTable.this, sessionImpl.clusterTranslator);
             if (sentinel.clusterId != sentinel.clusterUID.second)
-                throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                throw new RuntimeDatabaseException("ClusterTable corrupted.");
             create(sentinel);
             return sentinel;
         }
@@ -144,25 +146,25 @@ public final class ClusterTable implements IClusterTable {
             create(proxy);
             if (null != old) {
                 if (old.clusterKey != proxy.clusterKey)
-                    throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                    throw new RuntimeDatabaseException("ClusterTable corrupted.");
                 if (old.clusterId != proxy.clusterId)
-                    throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                    throw new RuntimeDatabaseException("ClusterTable corrupted.");
                 if (!old.clusterUID.equals(proxy.clusterUID))
-                    throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                    throw new RuntimeDatabaseException("ClusterTable corrupted.");
             }
         }
         private ClusterSmall freeProxy(ClusterImpl proxy) {
             ClusterImpl clusterImpl = hashMap.get(proxy.clusterId);
             if (null == clusterImpl)
-                throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                throw new RuntimeDatabaseException("ClusterTable corrupted.");
 //            ClusterUID clusterUID = ClusterUID.make(0, proxy.clusterId);
 //            ClusterImpl clusterImpl2 = clusterU2I.get(clusterUID );
 //            if (clusterImpl != clusterImpl2)
-//                throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+//                throw new RuntimeDatabaseException("ClusterTable corrupted.");
             if (proxy.clusterId != clusterImpl.clusterId)
-                throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                throw new RuntimeDatabaseException("ClusterTable corrupted.");
             if (proxy.clusterKey != clusterImpl.clusterKey)
-                throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                throw new RuntimeDatabaseException("ClusterTable corrupted.");
             ClusterSmall sentinel = new ClusterSmall(makeClusterUID(proxy.clusterId) , proxy.clusterKey, ClusterTable.this, sessionImpl.clusterTranslator);
             return (ClusterSmall)create(sentinel);
         }
@@ -280,7 +282,7 @@ public final class ClusterTable implements IClusterTable {
             ClusterImpl cluster = ClusterImpl.make(clusterUID, clusterKey, sessionImpl.clusterTranslator);
             clusters.create(cluster);
             if (!cluster.isLoaded())
-                Logger.defaultLogError(new Exception("Bug in ClusterTable.makeCluster(long, boolean), cluster not loaded"));
+                LOGGER.error("", new Exception("Bug in ClusterTable.makeCluster(long, boolean), cluster not loaded"));
             importanceMap.put(cluster.getImportance(), new ImportanceEntry(cluster));
             if (VALIDATE_SIZE)
                 validateSize("makeCluster");
@@ -289,14 +291,29 @@ public final class ClusterTable implements IClusterTable {
         }
     }
 
-    synchronized void replaceCluster(ClusterI cluster) {
-        //printMaps("replaceCluster");
+    synchronized void replaceCluster(ClusterI cluster_) {
+        ClusterImpl cluster = (ClusterImpl) cluster_;
         checkCollect();
         int clusterKey = cluster.getClusterKey();
-        ClusterI existing = clusterArray[clusterKey];
+        ClusterImpl existing = (ClusterImpl) clusterArray[clusterKey];
         if (existing.hasVirtual())
             cluster.markVirtual();
 
+        if (existing.cc != null) {
+            if (existing.isLoaded()) {
+                // This shall be promoted to actual exception in the future -
+                // for now, minimal changes
+                new Exception("Trying to replace cluster with pending changes " + existing.getClusterUID())
+                        .printStackTrace();
+            } else {
+                // Adopt changes to loaded cluster
+                cluster.cc = existing.cc;
+                cluster.cc.adopt(cluster);
+                cluster.foreignLookup = existing.foreignLookup;
+                cluster.change = existing.change;
+            }
+        }
+        
         importanceMap.remove(existing.getImportance());
         if (collectorPolicy != null)
             collectorPolicy.removed((ClusterImpl)existing);
@@ -305,7 +322,7 @@ public final class ClusterTable implements IClusterTable {
 
         clusters.replace((ClusterImpl)cluster);
         if (!cluster.isLoaded())
-            Logger.defaultLogError(new Exception("Bug in ClusterTable.replaceCluster(ClusterI), cluster not loaded"));
+            LOGGER.error("", new Exception("Bug in ClusterTable.replaceCluster(ClusterI), cluster not loaded"));
 
         importanceMap.put(cluster.getImportance(), new ImportanceEntry((ClusterImpl)cluster));
         if(collectorPolicy != null) collectorPolicy.added((ClusterImpl)cluster);
@@ -381,7 +398,7 @@ public final class ClusterTable implements IClusterTable {
                         result += cluster.getCachedSize();
                     }
                 } catch (Throwable t) {
-                    Logger.defaultLogError(t);
+                    LOGGER.error("Could not calculate size", t);
                 }
             }
             return true;
@@ -509,10 +526,11 @@ public final class ClusterTable implements IClusterTable {
                 ArrayList<CollectorCluster> toRelease = new ArrayList<CollectorCluster>();
 
                 for (CollectorCluster cluster : support.getResidentClusters()) {
-                    target -= support.getClusterSize(cluster);
-                    if (target > 0) {
-                        toRelease.add(cluster);
-                    } else {
+                    toRelease.add(cluster);
+                    long clusterSize = support.getClusterSize(cluster);
+                    //System.err.println("release cluster with " + (clusterSize/1024) + " kiB - " + cluster);
+                    target -= clusterSize;
+                    if (target <= 0) {
                         break;
                     }
                 }
@@ -580,7 +598,7 @@ public final class ClusterTable implements IClusterTable {
     void removeWriteOnlyClusters() {
         for (ClusterI proxy : writeOnlyClusters) {
             if (!(proxy instanceof ClusterImpl))
-                throw new RuntimeDatabaseException("ClusterTable corrupted. Contact application support.");
+                throw new RuntimeDatabaseException("ClusterTable corrupted.");
             clusters.freeProxy((ClusterImpl)proxy);
         }
         writeOnlyClusters.clear();
@@ -589,7 +607,6 @@ public final class ClusterTable implements IClusterTable {
             public boolean execute(int clusterKey) {
                 ClusterImpl proxy = clusterArray[clusterKey];
                 ClusterUID clusterUID = proxy.getClusterUID();
-                System.err.println("writeOnlyInvalidate " + clusterUID);
                 clusters.freeProxy(proxy);
                 return true;
             }
@@ -682,12 +699,12 @@ public final class ClusterTable implements IClusterTable {
     final long getClusterIdByResourceKeyNoThrow(final int resourceKey) {
         int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(resourceKey);
         if (ClusterTraitsBase.isVirtualClusterKey(clusterKey)) {
-            Logger.defaultLogError("Tried to get a persistent cluster for a virtual resource. key=" + resourceKey);
+            LOGGER.error("Tried to get a persistent cluster for a virtual resource. key=" + resourceKey);
             return 0;
         }
         ClusterI c = clusterArray[clusterKey];
         if (c == null) {
-            Logger.defaultLogError("No cluster for key " + resourceKey);
+            LOGGER.error("No cluster for key " + resourceKey);
             return 0;
         }
         return c.getClusterId();
@@ -745,14 +762,14 @@ public final class ClusterTable implements IClusterTable {
                         collectorPolicy.removed(oldCluster);
                     clusters.replace(newCluster);
                     if (!newCluster.isLoaded())
-                        Logger.defaultLogError(new Exception("Bug in ClusterTable.refresh, cluster not loaded"));
+                        LOGGER.error("", new Exception("Bug in ClusterTable.refresh, cluster not loaded"));
                     importanceMap.put(newCluster.getImportance(), new ImportanceEntry(newCluster));
                     if (collectorPolicy != null)
                         collectorPolicy.added(newCluster);
                     // Now we have fetched the new cluster but to emulate effects of the changes in it we fetch the cluster changes from server.
                     refreshCluster(csid, session, oldCluster, clusterUID[i], newCluster.clusterId, clusterKey);
                 } catch (Throwable t) {
-                    Logger.defaultLogError("Failed to load cluster in refresh.", t);
+                    LOGGER.error("Failed to load cluster in refresh.", t);
                 }
             }
             if (VALIDATE_SIZE)
@@ -765,9 +782,9 @@ public final class ClusterTable implements IClusterTable {
                 th = new TaskHelper("Refresh");
                 session.writeState = new WriteState<Object>(writer, th.writeTraits, th.sema, th.proc);
                 try {
-                    session.getQueryProvider2().performDirtyUpdates(writer);
+                    session.getQueryProvider2().propagateChangesInQueryCache(writer);
                     session.fireMetadataListeners(writer, cs);
-                    session.getQueryProvider2().performScheduledUpdates(writer);
+                    session.getQueryProvider2().listening.fireListeners(writer);
                     session.fireReactionsToSynchronize(cs);
                     session.fireSessionVariableChange(SessionVariables.QUEUED_WRITES);
                     session.printDiagnostics();
@@ -789,7 +806,7 @@ public final class ClusterTable implements IClusterTable {
         try {
             cc = session.graphSession.getClusterChanges(clusterUID, csid);
         } catch (Exception e) {
-            Logger.defaultLogError("Could not get cluster changes. cluster=" + clusterUID, e);
+            LOGGER.error("Could not get cluster changes. cluster=" + clusterUID, e);
             release(clusterId);
             return;
         }
@@ -812,7 +829,7 @@ public final class ClusterTable implements IClusterTable {
                 System.err.println("value " + cc.getValueIndex()[i] + " changed.");
         }
     }
-    final void refreshImportance(ClusterImpl c) {
+    final synchronized void refreshImportance(ClusterImpl c) {
 
         if (c.isWriteOnly())
             return;
@@ -826,7 +843,7 @@ public final class ClusterTable implements IClusterTable {
 // System.err.println("refreshImportance " + c.getClusterId() + " => " + newImportance);
         c.setImportance(newImportance);
         if (!c.isLoaded())
-            Logger.defaultLogError(new Exception("Bug in ClusterTable.refreshImportance(ClusterImpl), cluster not loaded"));
+            LOGGER.error("", new Exception("Bug in ClusterTable.refreshImportance(ClusterImpl), cluster not loaded"));
 
         importanceMap.put(c.getImportance(), new ImportanceEntry(c));
         if(collectorPolicy != null) collectorPolicy.added(c);
@@ -875,7 +892,7 @@ public final class ClusterTable implements IClusterTable {
                 cluster = load2(cs.getClusterId(), cs.getClusterKey());
             }
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("Could not load cluster", e);
             if (DebugPolicy.REPORT_CLUSTER_EVENTS)
                 e.printStackTrace();
             String msg = "Failed to load cluster " + cs.getClusterUID();// + " resourceId=" + (((cs.getClusterId() << 16 + (resourceKey & 65535))));
@@ -886,7 +903,7 @@ public final class ClusterTable implements IClusterTable {
     }
     
     @SuppressWarnings("unchecked")
-    public final <T extends ClusterI> T getClusterByResourceKey(final int resourceKey) {
+    public synchronized final <T extends ClusterI> T getClusterByResourceKey(final int resourceKey) {
         int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(resourceKey);
         if (ClusterTraitsBase.isVirtualClusterKey(clusterKey))
             throw new RuntimeException("Tried to get a persistent cluster for a virtual resource.");
@@ -899,7 +916,7 @@ public final class ClusterTable implements IClusterTable {
             return (T) c;
         }
         if (!(c instanceof ClusterSmall)) {
-            Logger.defaultLogError("Proxy must be instance of ClusterSmall");
+            LOGGER.error("Proxy must be instance of ClusterSmall");
             return null;
         }
         return ensureLoaded((T)c);
@@ -919,7 +936,7 @@ public final class ClusterTable implements IClusterTable {
             return (T) c;
         }
         if (!(c instanceof ClusterSmall)) {
-            Logger.defaultLogError("Proxy must be instance of ClusterSmall");
+            LOGGER.error("Proxy must be instance of ClusterSmall");
             return null;
         }
         ClusterI cluster;
@@ -933,7 +950,7 @@ public final class ClusterTable implements IClusterTable {
             int resourceIndex = resourceKey & ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(resourceKey);
             long resourceId = ClusterTraitsBase.createResourceIdNoThrow(cs.getClusterId(), resourceIndex);
             String msg = "Failed to load cluster " + cs.getClusterUID() + " for resource key " + resourceKey + " resourceIndex=" + resourceIndex + " resourceId=" + resourceId;
-            Logger.defaultLogError(msg, e);
+            LOGGER.error(msg, e);
             c.setDeleted(true, null);
             return (T)c;
         }
@@ -979,7 +996,7 @@ public final class ClusterTable implements IClusterTable {
         try {
             s.acquire();
         } catch (InterruptedException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("unable to acquire", e);
         }
         if (null != ex[0])
             throw ex[0];
@@ -1082,7 +1099,7 @@ public final class ClusterTable implements IClusterTable {
         } catch (Throwable t) {
             // It's totally legal to call for non-existing cluster.
             // Sometimes this indicates an error, though.
-            Logger.getDefault().logInfo("Load cluster failed.", t);
+            LOGGER.error("Load cluster failed", t);
             if (t instanceof DatabaseException)
                 e = (DatabaseException) t;
             else