diff --git a/gs-api/src/main/java/org/genericsystem/api/core/Filters.java b/gs-api/src/main/java/org/genericsystem/api/core/Filters.java new file mode 100644 index 000000000..f3e4515f1 --- /dev/null +++ b/gs-api/src/main/java/org/genericsystem/api/core/Filters.java @@ -0,0 +1,31 @@ +package org.genericsystem.api.core; + +import java.util.function.Function; + +public enum Filters { + + INSTANCES(vertex -> (x -> vertex.equals(x.getMeta()))), INHERITINGS(vertex -> (x -> x.getSupers().contains(vertex))), COMPOSITES(vertex -> (x -> x.getComponents().contains(vertex))); + + private Function, IndexFilter> getFilter; + + Filters(Function, IndexFilter> getFilter) { + this.getFilter = getFilter; + } + + public > IndexFilter getFilter(T generic) { + return getFilter.apply(generic); + } + + public static interface IndexFilter> { + boolean test(T generic); + } + + public static NoFilter NO_FILTER = new NoFilter<>(); + + public static class NoFilter> implements IndexFilter { + @Override + public boolean test(T generic) { + return true; + } + } +} diff --git a/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java b/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java index 4f755c666..769d0833a 100644 --- a/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java +++ b/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java @@ -133,6 +133,22 @@ public T get(Object o) { }; } + default > Snapshot filter(Filters filter, U generic) { + return new Snapshot() { + + @Override + public Stream stream() { + return Snapshot.this.stream().filter(g -> filter.getFilter(generic).test((U) g)); + } + + @Override + public T get(Object o) { + T result = Snapshot.this.get(o); + return result != null && filter.getFilter(generic).test((U) result) ? result : null; + } + }; + } + default List toList() { return stream().collect(Collectors.toList()); } diff --git a/gs-common/src/main/java/org/genericsystem/common/Differential.java b/gs-common/src/main/java/org/genericsystem/common/Differential.java index b5e57330a..0b9a638b9 100644 --- a/gs-common/src/main/java/org/genericsystem/common/Differential.java +++ b/gs-common/src/main/java/org/genericsystem/common/Differential.java @@ -2,16 +2,16 @@ import java.util.stream.Stream; -import javafx.beans.Observable; -import javafx.beans.property.IntegerProperty; -import javafx.beans.property.SimpleIntegerProperty; - import org.genericsystem.api.core.Snapshot; import org.genericsystem.api.core.exceptions.ConcurrencyControlException; import org.genericsystem.api.core.exceptions.OptimisticLockConstraintViolationException; import org.genericsystem.api.core.exceptions.RollbackException; import org.genericsystem.defaults.tools.BindingsTools; +import javafx.beans.Observable; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleIntegerProperty; + /** * @author Nicolas Feybesse * diff --git a/gs-common/src/main/java/org/genericsystem/common/IDependencies.java b/gs-common/src/main/java/org/genericsystem/common/IDependencies.java index 1c959116a..e0f413e71 100644 --- a/gs-common/src/main/java/org/genericsystem/common/IDependencies.java +++ b/gs-common/src/main/java/org/genericsystem/common/IDependencies.java @@ -2,6 +2,7 @@ import java.util.stream.Stream; +import org.genericsystem.api.core.Filters; import org.genericsystem.api.core.Snapshot; /** @@ -14,6 +15,8 @@ public interface IDependencies extends Snapshot { @Override Stream stream(); + Snapshot filter(Filters filter); + @Override T get(Object generic); diff --git a/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultContext.java b/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultContext.java index 6cec7b4b9..43ed79a7d 100644 --- a/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultContext.java +++ b/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultContext.java @@ -9,9 +9,8 @@ import java.util.Set; import java.util.TreeSet; -import javafx.collections.ObservableList; - import org.genericsystem.api.core.ApiStatics; +import org.genericsystem.api.core.Filters; import org.genericsystem.api.core.IContext; import org.genericsystem.api.core.Snapshot; import org.genericsystem.api.core.exceptions.ReferentialIntegrityConstraintViolationException; @@ -19,6 +18,8 @@ import org.genericsystem.api.core.exceptions.UnreachableOverridesException; import org.genericsystem.defaults.tools.SupersComputer; +import javafx.collections.ObservableList; + /** * @author Nicolas Feybesse * @@ -32,21 +33,27 @@ default boolean isAlive(T vertex) { assert vertex != null; class AliveFinder { T find(T vertex) { - if (vertex.isRoot()) + if (vertex.isRoot()) { + System.out.println("isAlive, isRoot " + vertex); return vertex; + } if (vertex.isMeta()) { T aliveSuper = new AliveFinder().find(vertex.getSupers().get(0)); + System.out.println("isAlive, isMeta " + vertex.info() + ", aliveSuper : " + aliveSuper.info() + ", résultat : " + (aliveSuper != null ? getInheritings(aliveSuper).get(vertex) : null)); return aliveSuper != null ? getInheritings(aliveSuper).get(vertex) : null; } T aliveMeta = new AliveFinder().find(vertex.getMeta()); + System.out.println("aliveMeta : " + aliveMeta + ", getInstances(aliveMeta).get(vertex) : " + getInstances(aliveMeta).get(vertex) + ", vertex : " + vertex); return aliveMeta != null ? getInstances(aliveMeta).get(vertex) : null; } } - return /* vertex != null && */vertex.equals(new AliveFinder().find(vertex)); + boolean result = vertex.equals(new AliveFinder().find(vertex)); + System.out.println("isAlive ? " + result); + return /* vertex != null && */result; } default Snapshot getInstances(T vertex) { - return getDependencies(vertex).filter(x -> vertex.equals(x.getMeta())); + return getDependencies(vertex).filter(Filters.INSTANCES, vertex); } default ObservableList getObservableInstances(T vertex) { @@ -54,7 +61,7 @@ default ObservableList getObservableInstances(T vertex) { } default Snapshot getInheritings(T vertex) { - return getDependencies(vertex).filter(x -> x.getSupers().contains(vertex)); + return getDependencies(vertex).filter(Filters.INHERITINGS, vertex); } default ObservableList getObservableInheritings(T vertex) { @@ -62,7 +69,7 @@ default ObservableList getObservableInheritings(T vertex) { } default Snapshot getComposites(T vertex) { - return getDependencies(vertex).filter(x -> x.getComponents().contains(vertex)); + return getDependencies(vertex).filter(Filters.COMPOSITES, vertex); } default ObservableList getObservableComposites(T vertex) { @@ -114,21 +121,17 @@ class OrderedRemoveDependencies extends TreeSet { OrderedRemoveDependencies visit(T node) { if (!contains(node)) { if (!getInheritings(node).isEmpty()) - discardWithException(new ReferentialIntegrityConstraintViolationException("Ancestor : " + node + " has a inheriting dependencies : " - + getInheritings(node).info())); + discardWithException(new ReferentialIntegrityConstraintViolationException("Ancestor : " + node + " has a inheriting dependencies : " + getInheritings(node).info())); getInheritings(node).forEach(this::visit); if (!getInstances(node).isEmpty()) - discardWithException(new ReferentialIntegrityConstraintViolationException("Ancestor : " + node + " has a instance dependencies : " - + getInstances(node).info())); + discardWithException(new ReferentialIntegrityConstraintViolationException("Ancestor : " + node + " has a instance dependencies : " + getInstances(node).info())); getInstances(node).forEach(this::visit); for (T composite : getComposites(node)) { for (int componentPos = 0; componentPos < composite.getComponents().size(); componentPos++) - if (composite.getComponents().get(componentPos).equals(node) && !contains(composite) - && composite.getMeta().isReferentialIntegrityEnabled(componentPos)) - discardWithException(new ReferentialIntegrityConstraintViolationException(composite + " is Referential Integrity for ancestor " - + node + " by composite position : " + componentPos)); + if (composite.getComponents().get(componentPos).equals(node) && !contains(composite) && composite.getMeta().isReferentialIntegrityEnabled(componentPos)) + discardWithException(new ReferentialIntegrityConstraintViolationException(composite + " is Referential Integrity for ancestor " + node + " by composite position : " + componentPos)); visit(composite); } add(node); diff --git a/gs-kernel/src/main/java/org/genericsystem/kernel/AbstractTsDependencies.java b/gs-kernel/src/main/java/org/genericsystem/kernel/AbstractTsDependencies.java index a890aaba3..cc5971a90 100644 --- a/gs-kernel/src/main/java/org/genericsystem/kernel/AbstractTsDependencies.java +++ b/gs-kernel/src/main/java/org/genericsystem/kernel/AbstractTsDependencies.java @@ -1,10 +1,13 @@ package org.genericsystem.kernel; +import java.util.Map; import java.util.Spliterators; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import org.genericsystem.api.core.Filters; +import org.genericsystem.api.core.Filters.IndexFilter; import org.genericsystem.common.AbstractIterator; import org.genericsystem.common.Generic; import org.genericsystem.kernel.AbstractServer.RootServerHandler; @@ -14,9 +17,112 @@ * */ abstract class AbstractTsDependencies { + private static interface Index { + public void add(Generic generic); + + public boolean remove(Generic generic); + + public Stream stream(long ts); + + } + + private class IndexImpl implements Index { + private Node head = null; + private Node tail = null; + + @Override + public void add(Generic generic) { + assert generic != null; + // assert getLifeManager().isWriteLockedByCurrentThread(); + Node newNode = new Node(generic); + if (head == null) + head = newNode; + else + tail.next = newNode; + tail = newNode; + Generic result = map.put(generic, generic); + assert result == null; + } + + @Override + public boolean remove(Generic generic) { + assert generic != null : "generic is null"; + assert head != null : "head is null"; + + Node currentNode = head; + + Generic currentContent = currentNode.content; + if (generic.equals(currentContent)) { + Node next = currentNode.next; + head = next != null ? next : null; + return true; + } + + Node nextNode = currentNode.next; + while (nextNode != null) { + Generic nextGeneric = nextNode.content; + Node nextNextNode = nextNode.next; + if (generic.equals(nextGeneric)) { + nextNode.content = null; + if (nextNextNode == null) + tail = currentNode; + currentNode.next = nextNextNode; + map.remove(generic); + return true; + } + currentNode = nextNode; + nextNode = nextNextNode; + } + return false; + } + + @Override + public Stream stream(long ts) { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new InternalIterator(ts), 0), false); + } + + private class InternalIterator extends AbstractIterator { + + private final long ts; + + private InternalIterator(long iterationTs) { + ts = iterationTs; + } + + @Override + protected void advance() { + for (;;) { + Node nextNode = (next == null) ? head : next.next; + if (nextNode == null) { + LifeManager lifeManager = getLifeManager(); + lifeManager.readLock(); + try { + nextNode = (next == null) ? head : next.next; + if (nextNode == null) { + next = null; + lifeManager.atomicAdjustLastReadTs(ts); + return; + } + } finally { + lifeManager.readUnlock(); + } + } + next = nextNode; + Generic content = next.content; + if (content != null && ((RootServerHandler) content.getProxyHandler()).getLifeManager().isAlive(ts)) + break; + + } + } + + @Override + protected Generic project() { + return next.content; + } + } + + } - private Node head = null; - private Node tail = null; private final ConcurrentHashMap map = new ConcurrentHashMap<>(); public abstract LifeManager getLifeManager(); @@ -39,92 +145,65 @@ public Generic get(Generic generic, long ts) { return null; } - public void add(Generic element) { - assert element != null; - // assert getLifeManager().isWriteLockedByCurrentThread(); - Node newNode = new Node(element); - if (head == null) - head = newNode; - else - tail.next = newNode; - tail = newNode; - Generic result = map.put(element, element); - assert result == null; - } - - public boolean remove(Generic generic) { - assert generic != null : "generic is null"; - assert head != null : "head is null"; - - Node currentNode = head; - - Generic currentContent = currentNode.content; - if (generic.equals(currentContent)) { - Node next = currentNode.next; - head = next != null ? next : null; - return true; - } + public Stream stream(long ts, IndexFilter filter) { + return indexs.get(filter).stream(ts); - Node nextNode = currentNode.next; - while (nextNode != null) { - Generic nextGeneric = nextNode.content; - Node nextNextNode = nextNode.next; - if (generic.equals(nextGeneric)) { - nextNode.content = null; - if (nextNextNode == null) - tail = currentNode; - currentNode.next = nextNextNode; - map.remove(generic); - return true; - } - currentNode = nextNode; - nextNode = nextNextNode; - } - return false; } public Stream stream(long ts) { - return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new InternalIterator(ts), 0), false); + return indexs.get(Filters.NO_FILTER).stream(ts); } - private class InternalIterator extends AbstractIterator { - - private final long ts; - - private InternalIterator(long iterationTs) { - ts = iterationTs; + // public static interface IndexFilter { + // boolean test(Generic generic); + // } + // + // private static NoFilter NO_FILTER = new NoFilter(); + // + // public static class NoFilter implements IndexFilter { + // @Override + // public boolean test(Generic generic) { + // return true; + // } + // } + + private final Map indexs = new ConcurrentHashMap() { + { + put(Filters.NO_FILTER, new IndexImpl()); } @Override - protected void advance() { - for (;;) { - Node nextNode = (next == null) ? head : next.next; - if (nextNode == null) { - LifeManager lifeManager = getLifeManager(); - lifeManager.readLock(); - try { - nextNode = (next == null) ? head : next.next; - if (nextNode == null) { - next = null; - lifeManager.atomicAdjustLastReadTs(ts); - return; - } - } finally { - lifeManager.readUnlock(); + public Index get(Object key) { + System.out.println("GGGGGGGGGGGGGGGGGGG get " + key); + return computeIfAbsent((IndexFilter) key, k -> { + System.out.println(" computeIfAbsent"); + return new IndexImpl() { + + @Override + public Stream stream(long ts) { + return super.stream(ts).filter(g -> ((IndexFilter) key).test(g)); } - } - next = nextNode; - Generic content = next.content; - if (content != null && ((RootServerHandler) content.getProxyHandler()).getLifeManager().isAlive(ts)) - break; - + }; + }); + }; + }; + + public void add(Generic generic) { + indexs.entrySet().forEach(entry -> { + if (entry.getKey().test(generic)) { + System.out.println("AAAAAAAAA ajout générique " + generic.info() + ", clef : " + entry.getKey()); + entry.getValue().add(generic); } - } + }); + } - @Override - protected Generic project() { - return next.content; - } + public boolean remove(Generic generic) { + boolean[] result = new boolean[] { false }; + indexs.entrySet().forEach(entry -> { + if (entry.getKey().test(generic)) + result[0] = result[0] | entry.getValue().remove(generic); + }); + return result[0]; } private static class Node { diff --git a/gs-kernel/src/main/java/org/genericsystem/kernel/Archiver.java b/gs-kernel/src/main/java/org/genericsystem/kernel/Archiver.java index 980e9db92..bae4a31b3 100644 --- a/gs-kernel/src/main/java/org/genericsystem/kernel/Archiver.java +++ b/gs-kernel/src/main/java/org/genericsystem/kernel/Archiver.java @@ -321,9 +321,10 @@ protected void loadDependency(Map vertexMap) throws IOException, List supers = loadAncestors(ts, vertexMap); List components = loadAncestors(ts, vertexMap); vertexMap.put(ts, new SetArchiverHandler(ts, context, meta, supers, value, components, otherTs).resolve()); - // log.info("load dependency : " + vertexMap.get(ts).info() + " " + ts + " " + vertexMap.get(ts).getTs() + " birthTs : " + - // vertexMap.get(ts).getLifeManager().getBirthTs()); - assert ((Transaction) context.getTransaction()).isAlive(vertexMap.get(ts)) : vertexMap.get(ts).info(); + log.info("load dependency : " + vertexMap.get(ts).info() + " " + ts + " " + vertexMap.get(ts).getTs() + " birthTs : " + ((RootServerHandler) vertexMap.get(ts).getProxyHandler()).getLifeManager().getBirthTs()); + System.out.println("alive ? " + vertexMap.get(ts) + " : " + ((Transaction) context.getTransaction()).isAlive(vertexMap.get(ts))); + assert ((Transaction) context.getTransaction()).isAlive(vertexMap.get(ts)) : ((RootServerHandler) vertexMap.get(ts).getProxyHandler()).getLifeManager().getBirthTs() + " " + + ((RootServerHandler) vertexMap.get(ts).getProxyHandler()).getLifeManager().getDeathTs() + " " + vertexMap.get(ts).info(); } protected List loadAncestors(long ts, Map vertexMap) throws IOException { diff --git a/gs-kernel/src/main/java/org/genericsystem/kernel/Transaction.java b/gs-kernel/src/main/java/org/genericsystem/kernel/Transaction.java index 6b3be25c8..06cb5fc8a 100644 --- a/gs-kernel/src/main/java/org/genericsystem/kernel/Transaction.java +++ b/gs-kernel/src/main/java/org/genericsystem/kernel/Transaction.java @@ -6,6 +6,8 @@ import java.util.Set; import java.util.stream.Stream; +import org.genericsystem.api.core.Filters; +import org.genericsystem.api.core.IGeneric; import org.genericsystem.api.core.Snapshot; import org.genericsystem.api.core.exceptions.ConcurrencyControlException; import org.genericsystem.api.core.exceptions.OptimisticLockConstraintViolationException; @@ -87,8 +89,28 @@ public Stream stream() { return ((RootServerHandler) ancestor.getProxyHandler()).getDependencies().stream(getTs()); } + @Override + public > Snapshot filter(Filters filter, U generic) { + System.out.println("===================== Filtre avec index 2"); + return new Snapshot() { + + @Override + public Stream stream() { + return ((RootServerHandler) ancestor.getProxyHandler()).getDependencies().stream(getTs(), filter.getFilter(generic)); + } + }; + } + + @Override + public Snapshot filter(Filters filter) { + System.out.println("===================== Filtre avec index"); + return filter(filter, ancestor); + } + @Override public Generic get(Object o) { + Generic result = ((RootServerHandler) ancestor.getProxyHandler()).getDependencies().get((Generic) o, getTs()); + System.out.println("get " + o + ", résultat : " + result); return ((RootServerHandler) ancestor.getProxyHandler()).getDependencies().get((Generic) o, getTs()); }