/** * Helper method that is the basis for operations that add mappings. */ private StateTableEntry<K, N, S> putEntry(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index]; e != null; e = e.next) { if (e.hash == hash && key.equals(e.key) && namespace.equals(e.namespace)) { // copy-on-write check for entry if (e.entryVersion < highestRequiredSnapshotVersion) { e = handleChainedEntryCopyOnWrite(tab, index, e); } return e; } } ++modCount; if (size() > threshold) { doubleCapacity(); } return addNewStateTableEntry(tab, key, namespace, hash); }
/** * Computes the hash for the composite of key and namespace and performs some steps of incremental rehash if * incremental rehashing is in progress. */ private int computeHashForOperationAndDoIncrementalRehash(K key, N namespace) { checkKeyNamespacePreconditions(key, namespace); if (isRehashing()) { incrementalRehash(); } return compositeHash(key, namespace); }
@Override public S get(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final int requiredVersion = highestRequiredSnapshotVersion; final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index]; e != null; e = e.next) { final K eKey = e.key; final N eNamespace = e.namespace; if ((e.hash == hash && key.equals(eKey) && namespace.equals(eNamespace))) { // copy-on-write check for state if (e.stateVersion < requiredVersion) { // copy-on-write check for entry if (e.entryVersion < requiredVersion) { e = handleChainedEntryCopyOnWrite(tab, hash & (tab.length - 1), e); } e.stateVersion = stateTableVersion; e.state = getStateSerializer().copy(e.state); } return e.state; } } return null; }
/** * Returns whether this table contains the specified key/namespace composite key. * * @param key the key in the composite key to search for. Not null. * @param namespace the namespace in the composite key to search for. Not null. * @return {@code true} if this map contains the specified key/namespace composite key, * {@code false} otherwise. */ boolean containsKey(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index]; e != null; e = e.next) { final K eKey = e.key; final N eNamespace = e.namespace; if ((e.hash == hash && key.equals(eKey) && namespace.equals(eNamespace))) { return true; } } return false; }
/** * Creates a new {@link CopyOnWriteStateTableSnapshot}. * * @param owningStateTable the {@link CopyOnWriteStateTable} for which this object represents a snapshot. */ CopyOnWriteStateTableSnapshot(CopyOnWriteStateTable<K, N, S> owningStateTable) { super(owningStateTable); this.snapshotData = owningStateTable.snapshotTableArrays(); this.snapshotVersion = owningStateTable.getStateTableVersion(); this.numberOfEntriesInSnapshotData = owningStateTable.size(); // We create duplicates of the serializers for the async snapshot, because TypeSerializer // might be stateful and shared with the event processing thread. this.localKeySerializer = owningStateTable.keyContext.getKeySerializer().duplicate(); this.localNamespaceSerializer = owningStateTable.metaInfo.getNamespaceSerializer().duplicate(); this.localStateSerializer = owningStateTable.metaInfo.getStateSerializer().duplicate(); this.partitionedStateTableSnapshot = null; }
/** * Helper method that is the basis for operations that remove mappings. */ private StateTableEntry<K, N, S> removeEntry(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && key.equals(e.key) && namespace.equals(e.namespace)) { if (prev == null) { tab[index] = e.next; } else { // copy-on-write check for entry if (prev.entryVersion < highestRequiredSnapshotVersion) { prev = handleChainedEntryCopyOnWrite(tab, index, prev); } prev.next = e.next; } ++modCount; if (tab == primaryTable) { --primaryTableSize; } else { --incrementalRehashTableSize; } return e; } } return null; }
/** * Maps the specified key/namespace composite key to the specified value. Returns the previous state that was * registered under the composite key. * * @param key the key. Not null. * @param namespace the namespace. Not null. * @param value the value. Can be null. * @return the value of any previous mapping with the specified key or * {@code null} if there was no such mapping. */ S putAndGetOld(K key, N namespace, S value) { final StateTableEntry<K, N, S> e = putEntry(key, namespace); // copy-on-write check for state S oldState = (e.stateVersion < highestRequiredSnapshotVersion) ? getStateSerializer().copy(e.state) : e.state; e.state = value; e.stateVersion = stateTableVersion; return oldState; }
/** * Removes the mapping with the specified key/namespace composite key from this map, returning the state that was * found under the entry. * * @param key the key of the mapping to remove. Not null. * @param namespace the namespace of the mapping to remove. Not null. * @return the value of the removed mapping or {@code null} if no mapping * for the specified key was found. */ S removeAndGetOld(K key, N namespace) { final StateTableEntry<K, N, S> e = removeEntry(key, namespace); return e != null ? // copy-on-write check for state (e.stateVersion < highestRequiredSnapshotVersion ? getStateSerializer().copy(e.state) : e.state) : null; }
@Override public boolean containsKey(N namespace) { return containsKey(keyContext.getCurrentKey(), namespace); }
@Override public S get(N namespace) { return get(keyContext.getCurrentKey(), namespace); }
/** * Creates a new {@link CopyOnWriteStateTableSnapshot}. * * @param owningStateTable the {@link CopyOnWriteStateTable} for which this object represents a snapshot. */ CopyOnWriteStateTableSnapshot(CopyOnWriteStateTable<K, N, S> owningStateTable) { super(owningStateTable); this.snapshotData = owningStateTable.snapshotTableArrays(); this.snapshotVersion = owningStateTable.getStateTableVersion(); this.stateTableSize = owningStateTable.size(); // We create duplicates of the serializers for the async snapshot, because TypeSerializer // might be stateful and shared with the event processing thread. this.localKeySerializer = owningStateTable.keyContext.getKeySerializer().duplicate(); this.localNamespaceSerializer = owningStateTable.metaInfo.getNamespaceSerializer().duplicate(); this.localStateSerializer = owningStateTable.metaInfo.getStateSerializer().duplicate(); this.keyGroupOffsets = null; }
/** * Helper method that is the basis for operations that remove mappings. */ private StateTableEntry<K, N, S> removeEntry(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && key.equals(e.key) && namespace.equals(e.namespace)) { if (prev == null) { tab[index] = e.next; } else { // copy-on-write check for entry if (prev.entryVersion < highestRequiredSnapshotVersion) { prev = handleChainedEntryCopyOnWrite(tab, index, prev); } prev.next = e.next; } ++modCount; if (tab == primaryTable) { --primaryTableSize; } else { --incrementalRehashTableSize; } return e; } } return null; }
/** * Maps the specified key/namespace composite key to the specified value. Returns the previous state that was * registered under the composite key. * * @param key the key. Not null. * @param namespace the namespace. Not null. * @param value the value. Can be null. * @return the value of any previous mapping with the specified key or * {@code null} if there was no such mapping. */ S putAndGetOld(K key, N namespace, S value) { final StateTableEntry<K, N, S> e = putEntry(key, namespace); // copy-on-write check for state S oldState = (e.stateVersion < highestRequiredSnapshotVersion) ? getStateSerializer().copy(e.state) : e.state; e.state = value; e.stateVersion = stateTableVersion; return oldState; }
/** * Removes the mapping with the specified key/namespace composite key from this map, returning the state that was * found under the entry. * * @param key the key of the mapping to remove. Not null. * @param namespace the namespace of the mapping to remove. Not null. * @return the value of the removed mapping or {@code null} if no mapping * for the specified key was found. */ S removeAndGetOld(K key, N namespace) { final StateTableEntry<K, N, S> e = removeEntry(key, namespace); return e != null ? // copy-on-write check for state (e.stateVersion < highestRequiredSnapshotVersion ? getStateSerializer().copy(e.state) : e.state) : null; }
/** * Returns whether this table contains the specified key/namespace composite key. * * @param key the key in the composite key to search for. Not null. * @param namespace the namespace in the composite key to search for. Not null. * @return {@code true} if this map contains the specified key/namespace composite key, * {@code false} otherwise. */ boolean containsKey(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index]; e != null; e = e.next) { final K eKey = e.key; final N eNamespace = e.namespace; if ((e.hash == hash && key.equals(eKey) && namespace.equals(eNamespace))) { return true; } } return false; }
@Override public boolean containsKey(N namespace) { return containsKey(keyContext.getCurrentKey(), namespace); }
@Override public S get(N namespace) { return get(keyContext.getCurrentKey(), namespace); }
/** * Helper method that is the basis for operations that add mappings. */ private StateTableEntry<K, N, S> putEntry(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index]; e != null; e = e.next) { if (e.hash == hash && key.equals(e.key) && namespace.equals(e.namespace)) { // copy-on-write check for entry if (e.entryVersion < highestRequiredSnapshotVersion) { e = handleChainedEntryCopyOnWrite(tab, index, e); } return e; } } ++modCount; if (size() > threshold) { doubleCapacity(); } return addNewStateTableEntry(tab, key, namespace, hash); }
/** * Computes the hash for the composite of key and namespace and performs some steps of incremental rehash if * incremental rehashing is in progress. */ private int computeHashForOperationAndDoIncrementalRehash(K key, N namespace) { checkKeyNamespacePreconditions(key, namespace); if (isRehashing()) { incrementalRehash(); } return compositeHash(key, namespace); }
@Override public S get(K key, N namespace) { final int hash = computeHashForOperationAndDoIncrementalRehash(key, namespace); final int requiredVersion = highestRequiredSnapshotVersion; final StateTableEntry<K, N, S>[] tab = selectActiveTable(hash); int index = hash & (tab.length - 1); for (StateTableEntry<K, N, S> e = tab[index]; e != null; e = e.next) { final K eKey = e.key; final N eNamespace = e.namespace; if ((e.hash == hash && key.equals(eKey) && namespace.equals(eNamespace))) { // copy-on-write check for state if (e.stateVersion < requiredVersion) { // copy-on-write check for entry if (e.entryVersion < requiredVersion) { e = handleChainedEntryCopyOnWrite(tab, hash & (tab.length - 1), e); } e.stateVersion = stateTableVersion; e.state = getStateSerializer().copy(e.state); } return e.state; } } return null; }