Migrate to tech.pantheon.TrieMap
[yangtools.git] / third-party / triemap / src / main / java / org / opendaylight / yangtools / triemap / INode.java
diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java
deleted file mode 100644 (file)
index 701d608..0000000
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * (C) Copyright 2016 Pantheon Technologies, s.r.o. and others.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.opendaylight.yangtools.triemap;
-
-import static org.opendaylight.yangtools.triemap.Constants.LEVEL_BITS;
-import static org.opendaylight.yangtools.triemap.LookupResult.RESTART;
-import static org.opendaylight.yangtools.triemap.PresencePredicate.ABSENT;
-import static org.opendaylight.yangtools.triemap.PresencePredicate.PRESENT;
-
-import com.google.common.base.VerifyException;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-
-final class INode<K, V> extends BasicNode {
-    @SuppressWarnings("rawtypes")
-    private static final AtomicReferenceFieldUpdater<INode, MainNode> MAINNODE_UPDATER =
-            AtomicReferenceFieldUpdater.newUpdater(INode.class, MainNode.class, "mainnode");
-
-    private final Gen gen;
-
-    private volatile MainNode<K, V> mainnode;
-
-    INode(final Gen gen, final MainNode<K, V> mainnode) {
-        this.gen = gen;
-        this.mainnode = mainnode;
-    }
-
-    MainNode<K, V> gcasRead(final TrieMap<?, ?> ct) {
-        return GCAS_READ(ct);
-    }
-
-    private MainNode<K, V> GCAS_READ(final TrieMap<?, ?> ct) {
-        MainNode<K, V> m = /* READ */ mainnode;
-        MainNode<K, V> prevval = /* READ */ m.readPrev();
-        if (prevval == null) {
-            return m;
-        }
-
-        return GCAS_Complete(m, ct);
-    }
-
-    private MainNode<K, V> GCAS_Complete(final MainNode<K, V> oldmain, final TrieMap<?, ?> ct) {
-        MainNode<K, V> m = oldmain;
-        while (m != null) {
-            // complete the GCAS
-            final MainNode<K, V> prev = /* READ */ m.readPrev();
-            final INode<?, ?> ctr = ct.readRoot(true);
-            if (prev == null) {
-                return m;
-            }
-
-            if (prev instanceof FailedNode) {
-                // try to commit to previous value
-                FailedNode<K, V> fn = (FailedNode<K, V>) prev;
-                if (MAINNODE_UPDATER.compareAndSet(this, m, fn.readPrev())) {
-                    return fn.readPrev();
-                }
-
-                // Tail recursion: return GCAS_Complete(/* READ */ mainnode, ct);
-                m = /* READ */ mainnode;
-                continue;
-            }
-
-            // Assume that you've read the root from the generation G.
-            // Assume that the snapshot algorithm is correct.
-            // ==> you can only reach nodes in generations <= G.
-            // ==> `gen` is <= G.
-            // We know that `ctr.gen` is >= G.
-            // ==> if `ctr.gen` = `gen` then they are both equal to G.
-            // ==> otherwise, we know that either `ctr.gen` > G, `gen` < G,
-            // or both
-            if (ctr.gen == gen && !ct.isReadOnly()) {
-                // try to commit
-                if (m.casPrev(prev, null)) {
-                    return m;
-                }
-
-                // Tail recursion: return GCAS_Complete(m, ct);
-                continue;
-            }
-
-            // try to abort
-            m.casPrev(prev, new FailedNode<>(prev));
-
-            // Tail recursion: return GCAS_Complete(/* READ */ mainnode, ct);
-            m = /* READ */ mainnode;
-        }
-
-        return null;
-    }
-
-    private boolean GCAS(final MainNode<K, V> old, final MainNode<K, V> n, final TrieMap<?, ?> ct) {
-        n.writePrev(old);
-        if (MAINNODE_UPDATER.compareAndSet(this, old, n)) {
-            GCAS_Complete(n, ct);
-            return /* READ */ n.readPrev() == null;
-        }
-
-        return false;
-    }
-
-    private INode<K, V> inode(final MainNode<K, V> cn) {
-        return new INode<>(gen, cn);
-    }
-
-    INode<K, V> copyToGen(final Gen ngen, final TrieMap<?, ?> ct) {
-        return new INode<>(ngen, GCAS_READ(ct));
-    }
-
-    /**
-     * Inserts a key value pair, overwriting the old pair if the keys match.
-     *
-     * @return true if successful, false otherwise
-     */
-    boolean recInsert(final K key, final V value, final int hc, final int lev, final INode<K, V> parent,
-            final TrieMap<K, V> ct) {
-        return recInsert(key, value, hc, lev, parent, gen, ct);
-    }
-
-    private boolean recInsert(final K k, final V v, final int hc, final int lev, final INode<K, V> parent,
-            final Gen startgen, final TrieMap<K, V> ct) {
-        while (true) {
-            final MainNode<K, V> m = GCAS_READ(ct);
-
-            if (m instanceof CNode) {
-                // 1) a multiway node
-                final CNode<K, V> cn = (CNode<K, V>) m;
-                final int idx = (hc >>> lev) & 0x1f;
-                final int flag = 1 << idx;
-                final int bmp = cn.bitmap;
-                final int mask = flag - 1;
-                final int pos = Integer.bitCount(bmp & mask);
-
-                if ((bmp & flag) != 0) {
-                    // 1a) insert below
-                    final BasicNode cnAtPos = cn.array[pos];
-                    if (cnAtPos instanceof INode) {
-                        final INode<K, V> in = (INode<K, V>) cnAtPos;
-                        if (startgen == in.gen) {
-                            return in.recInsert(k, v, hc, lev + LEVEL_BITS, this, startgen, ct);
-                        }
-                        if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
-                            // Tail recursion: return rec_insert(k, v, hc, lev, parent, startgen, ct);
-                            continue;
-                        }
-
-                        return false;
-                    } else if (cnAtPos instanceof SNode) {
-                        final SNode<K, V> sn = (SNode<K, V>) cnAtPos;
-                        if (sn.hc == hc && ct.equal(sn.key, k)) {
-                            return GCAS(cn, cn.updatedAt(pos, new SNode<>(k, v, hc), gen), ct);
-                        }
-
-                        final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-                        final MainNode<K, V> nn = rn.updatedAt(pos, inode(
-                            CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
-                        return GCAS(cn, nn, ct);
-                    } else {
-                        throw CNode.invalidElement(cnAtPos);
-                    }
-                }
-
-                final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-                final MainNode<K, V> ncnode = rn.insertedAt(pos, flag, new SNode<>(k, v, hc), gen);
-                return GCAS(cn, ncnode, ct);
-            } else if (m instanceof TNode) {
-                clean(parent, ct, lev - LEVEL_BITS);
-                return false;
-            } else if (m instanceof LNode) {
-                final LNode<K, V> ln = (LNode<K, V>) m;
-                final LNodeEntry<K, V> entry = ln.get(ct.equiv(), k);
-                return entry != null ? replaceln(ln, entry, v, ct) : insertln(ln, k, v, ct);
-            } else {
-                throw invalidElement(m);
-            }
-        }
-    }
-
-    private static VerifyException invalidElement(final BasicNode elem) {
-        throw new VerifyException("An INode can host only a CNode, a TNode or an LNode, not " + elem);
-    }
-
-    @SuppressFBWarnings(value = "NP_OPTIONAL_RETURN_NULL",
-            justification = "Returning null Optional indicates the need to restart.")
-    private Optional<V> insertDual(final TrieMap<K, V> ct, final CNode<K, V> cn, final int pos, final SNode<K, V> sn,
-            final K k, final V v, final int hc, final int lev) {
-        final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-        final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
-        return GCAS(cn, nn, ct) ? Optional.empty() : null;
-    }
-
-    /**
-     * Inserts a new key value pair, given that a specific condition is met.
-     *
-     * @param cond
-     *            null - don't care if the key was there
-     *            KEY_ABSENT - key wasn't there
-     *            KEY_PRESENT - key was there
-     *            other value `v` - key must be bound to `v`
-     * @return null if unsuccessful, Option[V] otherwise (indicating
-     *         previous value bound to the key)
-     */
-    Optional<V> recInsertIf(final K k, final V v, final int hc, final Object cond, final int lev,
-            final INode<K, V> parent, final TrieMap<K, V> ct) {
-        return recInsertIf(k, v, hc, cond, lev, parent, gen, ct);
-    }
-
-    @SuppressFBWarnings(value = "NP_OPTIONAL_RETURN_NULL",
-            justification = "Returning null Optional indicates the need to restart.")
-    private Optional<V> recInsertIf(final K k, final V v, final int hc, final Object cond, final int lev,
-            final INode<K, V> parent, final Gen startgen, final TrieMap<K, V> ct) {
-        while (true) {
-            final MainNode<K, V> m = GCAS_READ(ct);
-
-            if (m instanceof CNode) {
-                // 1) a multiway node
-                final CNode<K, V> cn = (CNode<K, V>) m;
-                final int idx = (hc >>> lev) & 0x1f;
-                final int flag = 1 << idx;
-                final int bmp = cn.bitmap;
-                final int mask = flag - 1;
-                final int pos = Integer.bitCount(bmp & mask);
-
-                if ((bmp & flag) != 0) {
-                    // 1a) insert below
-                    final BasicNode cnAtPos = cn.array[pos];
-                    if (cnAtPos instanceof INode) {
-                        final INode<K, V> in = (INode<K, V>) cnAtPos;
-                        if (startgen == in.gen) {
-                            return in.recInsertIf(k, v, hc, cond, lev + LEVEL_BITS, this, startgen, ct);
-                        }
-
-                        if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
-                            // Tail recursion: return rec_insertif(k, v, hc, cond, lev, parent, startgen, ct);
-                            continue;
-                        }
-
-                        return null;
-                    } else if (cnAtPos instanceof SNode) {
-                        final SNode<K, V> sn = (SNode<K, V>) cnAtPos;
-                        if (cond == null) {
-                            if (sn.hc == hc && ct.equal(sn.key, k)) {
-                                if (GCAS(cn, cn.updatedAt(pos, new SNode<>(k, v, hc), gen), ct)) {
-                                    return Optional.of(sn.value);
-                                }
-
-                                return null;
-                            }
-
-                            return insertDual(ct, cn, pos, sn, k, v, hc, lev);
-                        } else if (cond == ABSENT) {
-                            if (sn.hc == hc && ct.equal(sn.key, k)) {
-                                return Optional.of(sn.value);
-                            }
-
-                            return insertDual(ct, cn, pos, sn, k, v, hc, lev);
-                        } else if (cond == PRESENT) {
-                            if (sn.hc == hc && ct.equal(sn.key, k)) {
-                                if (GCAS(cn, cn.updatedAt(pos, new SNode<>(k, v, hc), gen), ct)) {
-                                    return Optional.of(sn.value);
-                                }
-                                return null;
-                            }
-
-                            return Optional.empty();
-                        } else {
-                            if (sn.hc == hc && ct.equal(sn.key, k) && cond.equals(sn.value)) {
-                                if (GCAS(cn, cn.updatedAt(pos, new SNode<>(k, v, hc), gen), ct)) {
-                                    return Optional.of(sn.value);
-                                }
-
-                                return null;
-                            }
-
-                            return Optional.empty();
-                        }
-                    } else {
-                        throw CNode.invalidElement(cnAtPos);
-                    }
-                } else if (cond == null || cond == ABSENT) {
-                    final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-                    final CNode<K, V> ncnode = rn.insertedAt(pos, flag, new SNode<>(k, v, hc), gen);
-                    if (GCAS(cn, ncnode, ct)) {
-                        return Optional.empty();
-                    }
-
-                    return null;
-                } else {
-                    return Optional.empty();
-                }
-            } else if (m instanceof TNode) {
-                clean(parent, ct, lev - LEVEL_BITS);
-                return null;
-            } else if (m instanceof LNode) {
-                // 3) an l-node
-                final LNode<K, V> ln = (LNode<K, V>) m;
-                final LNodeEntry<K, V> entry = ln.get(ct.equiv(), k);
-
-                if (cond == null) {
-                    if (entry != null) {
-                        return replaceln(ln, entry, v, ct) ? Optional.of(entry.getValue()) : null;
-                    }
-
-                    return insertln(ln, k, v, ct) ? Optional.empty() : null;
-                } else if (cond == ABSENT) {
-                    if (entry != null) {
-                        return Optional.of(entry.getValue());
-                    }
-
-                    return insertln(ln, k, v, ct) ? Optional.empty() : null;
-                } else if (cond == PRESENT) {
-                    if (entry == null) {
-                        return Optional.empty();
-                    }
-
-                    return replaceln(ln, entry, v, ct) ? Optional.of(entry.getValue()) : null;
-                } else {
-                    if (entry == null || !cond.equals(entry.getValue())) {
-                        return Optional.empty();
-                    }
-
-                    return replaceln(ln, entry, v, ct) ? Optional.of(entry.getValue()) : null;
-                }
-            } else {
-                throw invalidElement(m);
-            }
-        }
-    }
-
-    private boolean insertln(final LNode<K, V> ln, final K k, final V v, final TrieMap<K, V> ct) {
-        return GCAS(ln, ln.insertChild(k, v), ct);
-    }
-
-    private boolean replaceln(final LNode<K, V> ln, final LNodeEntry<K, V> entry, final V v, final TrieMap<K, V> ct) {
-        return GCAS(ln, ln.replaceChild(entry, v), ct);
-    }
-
-    /**
-     * Looks up the value associated with the key.
-     *
-     * @return null if no value has been found, RESTART if the operation
-     *         wasn't successful, or any other value otherwise
-     */
-    Object recLookup(final K k, final int hc, final int lev, final INode<K, V> parent, final TrieMap<K, V> ct) {
-        return recLookup(k, hc, lev, parent, gen, ct);
-    }
-
-    private Object recLookup(final K k, final int hc, final int lev, final INode<K, V> parent, final Gen startgen,
-            final TrieMap<K, V> ct) {
-        while (true) {
-            final MainNode<K, V> m = GCAS_READ(ct);
-
-            if (m instanceof CNode) {
-                // 1) a multinode
-                final CNode<K, V> cn = (CNode<K, V>) m;
-                final int idx = (hc >>> lev) & 0x1f;
-                final int flag = 1 << idx;
-                final int bmp = cn.bitmap;
-
-                if ((bmp & flag) == 0) {
-                    // 1a) bitmap shows no binding
-                    return null;
-                }
-
-                // 1b) bitmap contains a value - descend
-                final int pos = (bmp == 0xffffffff) ? idx : Integer.bitCount(bmp & (flag - 1));
-                final BasicNode sub = cn.array[pos];
-                if (sub instanceof INode) {
-                    final INode<K, V> in = (INode<K, V>) sub;
-                    if (ct.isReadOnly() || (startgen == in.gen)) {
-                        return in.recLookup(k, hc, lev + LEVEL_BITS, this, startgen, ct);
-                    }
-
-                    if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
-                        // Tail recursion: return rec_lookup(k, hc, lev, parent, startgen, ct);
-                        continue;
-                    }
-
-                    return RESTART;
-                } else if (sub instanceof SNode) {
-                    // 2) singleton node
-                    final SNode<K, V> sn = (SNode<K, V>) sub;
-                    if (sn.hc == hc && ct.equal(sn.key, k)) {
-                        return sn.value;
-                    }
-
-                    return null;
-                } else {
-                    throw CNode.invalidElement(sub);
-                }
-            } else if (m instanceof TNode) {
-                // 3) non-live node
-                return cleanReadOnly((TNode<K, V>) m, lev, parent, ct, k, hc);
-            } else if (m instanceof LNode) {
-                // 5) an l-node
-                final LNodeEntry<K, V> entry = ((LNode<K, V>) m).get(ct.equiv(), k);
-                return entry != null ? entry.getValue() : null;
-            } else {
-                throw invalidElement(m);
-            }
-        }
-    }
-
-    private Object cleanReadOnly(final TNode<K, V> tn, final int lev, final INode<K, V> parent,
-            final TrieMap<K, V> ct, final K k, final int hc) {
-        if (ct.isReadOnly()) {
-            if (tn.hc == hc && ct.equal(tn.key, k)) {
-                return tn.value;
-            }
-
-            return null;
-        }
-
-        clean(parent, ct, lev - LEVEL_BITS);
-        return RESTART;
-    }
-
-    /**
-     * Removes the key associated with the given value.
-     *
-     * @param cond
-     *            if null, will remove the key regardless of the value;
-     *            otherwise removes only if binding contains that exact key
-     *            and value
-     * @return null if not successful, an Optional indicating the previous
-     *         value otherwise
-     */
-    Optional<V> recRemove(final K k, final Object cond, final int hc, final int lev, final INode<K, V> parent,
-            final TrieMap<K, V> ct) {
-        return recRemove(k, cond, hc, lev, parent, gen, ct);
-    }
-
-    @SuppressFBWarnings(value = "NP_OPTIONAL_RETURN_NULL",
-            justification = "Returning null Optional indicates the need to restart.")
-    private Optional<V> recRemove(final K k, final Object cond, final int hc, final int lev, final INode<K, V> parent,
-            final Gen startgen, final TrieMap<K, V> ct) {
-        final MainNode<K, V> m = GCAS_READ(ct);
-
-        if (m instanceof CNode) {
-            final CNode<K, V> cn = (CNode<K, V>) m;
-            final int idx = (hc >>> lev) & 0x1f;
-            final int bmp = cn.bitmap;
-            final int flag = 1 << idx;
-            if ((bmp & flag) == 0) {
-                return Optional.empty();
-            }
-
-            final int pos = Integer.bitCount(bmp & (flag - 1));
-            final BasicNode sub = cn.array[pos];
-            final Optional<V> res;
-            if (sub instanceof INode) {
-                final INode<K, V> in = (INode<K, V>) sub;
-                if (startgen == in.gen) {
-                    res = in.recRemove(k, cond, hc, lev + LEVEL_BITS, this, startgen, ct);
-                } else {
-                    if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
-                        res = recRemove(k, cond, hc, lev, parent, startgen, ct);
-                    } else {
-                        res = null;
-                    }
-                }
-            } else if (sub instanceof SNode) {
-                final SNode<K, V> sn = (SNode<K, V>) sub;
-                if (sn.hc == hc && ct.equal(sn.key, k) && (cond == null || cond.equals(sn.value))) {
-                    final MainNode<K, V> ncn = cn.removedAt(pos, flag, gen).toContracted(lev);
-                    if (GCAS(cn, ncn, ct)) {
-                        res = Optional.of(sn.value);
-                    } else {
-                        res = null;
-                    }
-                } else {
-                    res = Optional.empty();
-                }
-            } else {
-                throw CNode.invalidElement(sub);
-            }
-
-            if (res == null || !res.isPresent()) {
-                return res;
-            }
-
-            if (parent != null) {
-                // never tomb at root
-                final MainNode<K, V> n = GCAS_READ(ct);
-                if (n instanceof TNode) {
-                    cleanParent(n, parent, ct, hc, lev, startgen);
-                }
-            }
-
-            return res;
-        } else if (m instanceof TNode) {
-            clean(parent, ct, lev - LEVEL_BITS);
-            return null;
-        } else if (m instanceof LNode) {
-            final LNode<K, V> ln = (LNode<K, V>) m;
-            final LNodeEntry<K, V> entry = ln.get(ct.equiv(), k);
-            if (entry == null) {
-                // Key was not found, hence no modification is needed
-                return Optional.empty();
-            }
-
-            final V value = entry.getValue();
-            if (cond != null && !cond.equals(value)) {
-                // Value does not match
-                return Optional.empty();
-            }
-
-            return GCAS(ln, ln.removeChild(entry, hc), ct) ? Optional.of(value) : null;
-        } else {
-            throw invalidElement(m);
-        }
-    }
-
-    private void cleanParent(final Object nonlive, final INode<K, V> parent, final TrieMap<K, V> ct, final int hc,
-            final int lev, final Gen startgen) {
-        while (true) {
-            final MainNode<K, V> pm = parent.GCAS_READ(ct);
-            if ((!(pm instanceof CNode))) {
-                // parent is no longer a cnode, we're done
-                return;
-            }
-
-            final CNode<K, V> cn = (CNode<K, V>) pm;
-            final int idx = (hc >>> (lev - LEVEL_BITS)) & 0x1f;
-            final int bmp = cn.bitmap;
-            final int flag = 1 << idx;
-            if ((bmp & flag) == 0) {
-                // somebody already removed this i-node, we're done
-                return;
-            }
-
-            final int pos = Integer.bitCount(bmp & (flag - 1));
-            final BasicNode sub = cn.array[pos];
-            if (sub == this && nonlive instanceof TNode) {
-                final TNode<?, ?> tn = (TNode<?, ?>) nonlive;
-                final MainNode<K, V> ncn = cn.updatedAt(pos, tn.copyUntombed(), gen).toContracted(lev - LEVEL_BITS);
-                if (!parent.GCAS(cn, ncn, ct)) {
-                    if (ct.readRoot().gen == startgen) {
-                        // Tail recursion: cleanParent(nonlive, parent, ct, hc, lev, startgen);
-                        continue;
-                    }
-                }
-            }
-            break;
-        }
-    }
-
-    private void clean(final INode<K, V> nd, final TrieMap<K, V> ct, final int lev) {
-        final MainNode<K, V> m = nd.GCAS_READ(ct);
-        if (m instanceof CNode) {
-            final CNode<K, V> cn = (CNode<K, V>) m;
-            nd.GCAS(cn, cn.toCompressed(ct, lev, gen), ct);
-        }
-    }
-
-    int size(final ImmutableTrieMap<?, ?> ct) {
-        return GCAS_READ(ct).size(ct);
-    }
-}