Interface KeyValueTable<KeyT,​ValueT>

  • Type Parameters:
    KeyT - Table Key Type.
    ValueT - Table Value Type.
    All Superinterfaces:
    java.lang.AutoCloseable

    @Beta
    public interface KeyValueTable<KeyT,​ValueT>
    extends java.lang.AutoCloseable
    Defines all operations that are supported on a Key-Value Table.

    A Key-Value Table is a distributed Key-Value Store that indexes Entries by Keys. It uses Table Segments (non-distributed Key-Value Store backed by a single Pravega Segment) as the fundamental storage primitive and provides a unified view of all Table Segments involved. Each TableKey is hashed to a Table Partition which may be represented by one or more Table Segments (depending on the Key-Value Table configuration chosen when it was created). Such partitioning enables the Key-Value Table to be distributed across the Pravega cluster but also introduces some constraints for certain operations (such as multi-key/entry atomic updates). See below for details.

    Key Families are used to group related Keys together in the same Table Partition, which allows multiple keys/entries belonging to the same Key Family to be updated/removed atomically.

    • Multiple Keys/Entries in the same Key Family can be updated or removed atomically (either all changes will be applied or none will).
    • Iterating through all Keys/Entries in the same Key Family is possible.
    • The same Key may exist in multiple Key Families or even not be associated with any Key Family at all. Such keys are treated as distinct keys and will not interfere with each other (i.e., if key K1 exists in Key Families F1 and F2, then F1.K1 is different from F2.K1 and both are different from K1 (no Key Family association).
    • Keys that do not belong to any Key Family will be uniformly distributed across the Key-Value Table Partitions and cannot be used for multi-key/entry atomic updates or removals or be iterated on.
    • Keys belonging to the same Key Family are grouped into the same Table Segment; as such, the choice of Key Families can have performance implications. An ideally balanced Key-Value Table is one where no Key is part of any Key Family or the number of Keys in each Key Family is approximately the same. To enable a uniform distribution of Keys over the Key-Value Table, it is highly recommended not to use Key Families at all. If this situation cannot be avoided (i.e., multi-entry atomic updates or iterators are required), then it is recommended that Key Families themselves be diversified and Keys be equally distributed across them. Such approaches will ensure that the Key-Value Table load will be spread across all its Table Segments. An undesirable situation is an extreme case where all the Keys in the Key-Value Table are associated with a single Key Family; in this case the entire Key-Value Table load will be placed on a single backing Table Segment instead of spreading it across many Table Segments, leading to eventual performance degradation.

    Types of Updates:

    • Unconditional Updates will insert and/or overwrite any existing values for the given Key, regardless of whether that Key previously existed or not, and regardless of what that Key's version is. Such updates can be performed using put(String, Object, Object) or putAll(String, Iterable).
    • Conditional Updates will only overwrite an existing value if the specified Version matches the one that is currently present on the server. Conditional inserts can be performed using putIfAbsent(String, Object, Object) and will only succeed if the given Key does not already exist in the given Key Family. Conditional updates can be performed using replace(String, Object, Object, Version).
    • Unconditional Removals will remove a Key regardless of what that Key's version is. The operation will also succeed (albeit with no effect) if the Key does not exist. Such removals can be performed using remove(String, Object).
    • Conditional Removals will remove a Key only if the specified Version matches the one that is currently present on the server. Such removals can be performed using remove(String, Object, Version).
    • Multi-key updates allow mixing different types of updates in the same update batch. Some entries may be conditioned on their Keys not existing at all (TableEntry.getKey()TableKey.getVersion() equals Version.NOT_EXISTS), some may be conditioned on specific versions and some may not have condition attached at all (TableEntry.getKey()TableKey.getVersion() equals Version.NO_VERSION). All the conditions that are present in the update batch must be satisfied in order for the update batch to be accepted - the condition checks and updates are performed atomically. Use replaceAll(String, Iterable) for such an update.
    • Multi-key removals allow mixing different types of removals in the same removal batch. Some removals may be conditioned on their affected Keys having a specific version and some may not have a condition attached at all (TableKey.getVersion() equals Version.NO_VERSION). Although unusual, it is possible to have a removal conditioned on a Key not existing (TableKey.getVersion() equals Version.NOT_EXISTS); such an update will have no effect on that Key if it doesn't exist but it will prevent the rest of the removals from the same batch from being applied - this can be used in scenarios where a set of Keys must be removed only if a particular Key is not present. All the conditions that are present in the removal batch must be satisfied in order for the removal batch to be accepted - the condition checks and updates are performed atomically. Use removeAll(String, Iterable) for such a removal.

    Conditional Update Responses:

    • Success: the update or removal has been atomically validated and performed; all updates or removals in the request have been accepted.
    • Failure: the update or removal has been rejected due to version mismatch; no update or removal has been performed.
    • NoSuchKeyException: the update or removal has been conditioned on a specific version (different from Version.NOT_EXISTS or Version.NO_VERSION) but the Key does not exist in the KeyValueTable.
    • BadKeyVersionException: the update or removal has been conditioned on a specific version (different from Version.NO_VERSION but the Key exists in the KeyValueTable with a different version.
    • Method Summary

      All Methods Instance Methods Abstract Methods 
      Modifier and Type Method Description
      void close()
      Closes the KeyValueTable.
      io.pravega.common.util.AsyncIterator<IteratorItem<TableEntry<KeyT,​ValueT>>> entryIterator​(@NonNull java.lang.String keyFamily, int maxEntriesAtOnce, IteratorState state)
      Creates a new Iterator over all the TableEntry instances in this KeyValueTable that belong to a specific Key Family.
      java.util.concurrent.CompletableFuture<TableEntry<KeyT,​ValueT>> get​(java.lang.String keyFamily, KeyT key)
      Gets the latest value for the a Key that belong to a specific Key Family.
      java.util.concurrent.CompletableFuture<java.util.List<TableEntry<KeyT,​ValueT>>> getAll​(java.lang.String keyFamily, @NonNull java.lang.Iterable<KeyT> keys)
      Gets the latest values for a set of Keys that do belong to the same Key Family.
      KeyValueTableMap<KeyT,​ValueT> getMapFor​(java.lang.String keyFamily)
      Exposes this KeyValueTable instance as a Map.
      io.pravega.common.util.AsyncIterator<IteratorItem<TableKey<KeyT>>> keyIterator​(@NonNull java.lang.String keyFamily, int maxKeysAtOnce, IteratorState state)
      Creates a new Iterator over all the TableKeys in this KeyValueTable that belong to a specific Key Family.
      java.util.concurrent.CompletableFuture<Version> put​(java.lang.String keyFamily, KeyT key, ValueT value)
      Unconditionally inserts a new or updates an existing Entry in the KeyValueTable.
      java.util.concurrent.CompletableFuture<java.util.List<Version>> putAll​(@NonNull java.lang.String keyFamily, @NonNull java.lang.Iterable<java.util.Map.Entry<KeyT,​ValueT>> entries)
      Unconditionally inserts new or updates existing TableEntry instances that belong to the same Key Family into this KeyValueTable.
      java.util.concurrent.CompletableFuture<Version> putIfAbsent​(java.lang.String keyFamily, KeyT key, ValueT value)
      Conditionally inserts a new Entry in the KeyValueTable if the given Key is not already present.
      java.util.concurrent.CompletableFuture<java.lang.Void> remove​(java.lang.String keyFamily, KeyT key)
      Unconditionally removes a Key from this Table Segment.
      java.util.concurrent.CompletableFuture<java.lang.Void> remove​(java.lang.String keyFamily, KeyT key, @NonNull Version version)
      Conditionally Removes a Key from this Table Segment.
      java.util.concurrent.CompletableFuture<java.lang.Void> removeAll​(java.lang.String keyFamily, @NonNull java.lang.Iterable<TableKey<KeyT>> keys)
      Removes one or more TableKey instances that belong to the same Key Family from this Table Segment.
      java.util.concurrent.CompletableFuture<Version> replace​(java.lang.String keyFamily, KeyT key, ValueT value, @NonNull Version version)
      Conditionally updates an existing Entry in the KeyValueTable if the given Key exists and its version matches the given Version.
      java.util.concurrent.CompletableFuture<java.util.List<Version>> replaceAll​(@NonNull java.lang.String keyFamily, @NonNull java.lang.Iterable<TableEntry<KeyT,​ValueT>> entries)
      Inserts new or updates existing TableEntry instances that belong to the same Key Family into this KeyValueTable.
    • Field Detail

      • MAXIMUM_SERIALIZED_KEY_LENGTH

        static final int MAXIMUM_SERIALIZED_KEY_LENGTH
        The maximum serialization length of a Table Segment Key.
        See Also:
        Constant Field Values
      • MAXIMUM_SERIALIZED_VALUE_LENGTH

        static final int MAXIMUM_SERIALIZED_VALUE_LENGTH
        The maximum serialized length of a Table Segment Value.
        See Also:
        Constant Field Values
    • Method Detail

      • put

        java.util.concurrent.CompletableFuture<Version> put​(@Nullable
                                                            java.lang.String keyFamily,
                                                            @NonNull
                                                            KeyT key,
                                                            @NonNull
                                                            ValueT value)
        Unconditionally inserts a new or updates an existing Entry in the KeyValueTable.
        Parameters:
        keyFamily - (Optional) The Key Family for the Entry. If null, this Entry will not be associated with any Key Family.
        key - The Key to insert or update.
        value - The Value to be associated with the Key.
        Returns:
        A CompletableFuture that, when completed, will contain the Version associated with the newly inserted or updated entry.
      • putIfAbsent

        java.util.concurrent.CompletableFuture<Version> putIfAbsent​(@Nullable
                                                                    java.lang.String keyFamily,
                                                                    @NonNull
                                                                    KeyT key,
                                                                    @NonNull
                                                                    ValueT value)
        Conditionally inserts a new Entry in the KeyValueTable if the given Key is not already present.
        Parameters:
        keyFamily - (Optional) The Key Family for the Entry. If null, this Entry will not be associated with any Key Family.
        key - The Key to insert.
        value - The Value to be associated with the Key.
        Returns:
        A CompletableFuture that, when completed, will contain the Version associated with the newly inserted or updated entry. Notable exceptions:
      • putAll

        java.util.concurrent.CompletableFuture<java.util.List<Version>> putAll​(@NonNull
                                                                               @NonNull java.lang.String keyFamily,
                                                                               @NonNull
                                                                               @NonNull java.lang.Iterable<java.util.Map.Entry<KeyT,​ValueT>> entries)
        Unconditionally inserts new or updates existing TableEntry instances that belong to the same Key Family into this KeyValueTable. All changes are performed atomically (either all or none will be accepted).
        Parameters:
        keyFamily - The Key Family for the all provided Table Entries.
        entries - An Iterable of Map.Entry instances to insert or update.
        Returns:
        A CompletableFuture that, when completed, will contain a List of Version instances which represent the versions for the inserted/updated keys. The size of this list will be the same as the number of items in entries and the versions will be in the same order as the entries.
      • replace

        java.util.concurrent.CompletableFuture<Version> replace​(@Nullable
                                                                java.lang.String keyFamily,
                                                                @NonNull
                                                                KeyT key,
                                                                @NonNull
                                                                ValueT value,
                                                                @NonNull
                                                                @NonNull Version version)
        Conditionally updates an existing Entry in the KeyValueTable if the given Key exists and its version matches the given Version.
        Parameters:
        keyFamily - (Optional) The Key Family for the Entry. If null, this Entry will not be associated with any Key Family.
        key - The Key to update.
        value - The new Value to be associated with the Key.
        version - A Version representing the version that this Key must have in order to replace it.
        Returns:
        A CompletableFuture that, when completed, will contain the Version associated with the updated entry. Notable exceptions:
      • replaceAll

        java.util.concurrent.CompletableFuture<java.util.List<Version>> replaceAll​(@NonNull
                                                                                   @NonNull java.lang.String keyFamily,
                                                                                   @NonNull
                                                                                   @NonNull java.lang.Iterable<TableEntry<KeyT,​ValueT>> entries)
        Inserts new or updates existing TableEntry instances that belong to the same Key Family into this KeyValueTable. All changes are performed atomically (either all or none will be accepted).
        Parameters:
        keyFamily - The Key Family for the all provided TableEntry instances.
        entries - An Iterable of TableEntry instances to insert or update. If for at least one such entry, TableEntry.getKey()TableKey.getVersion() indicates a conditional update, this will perform an atomic Conditional Update conditioned on the server-side versions matching the provided ones (for all TableEntry instances that have one); otherwise an Unconditional Update will be performed. See KeyValueTable doc for more details on Types of Updates.
        Returns:
        A CompletableFuture that, when completed, will contain a List of Version instances which represent the versions for the inserted/updated keys. The size of this list will be the same as entries.size() and the versions will be in the same order as the entries. Notable exceptions:
      • remove

        java.util.concurrent.CompletableFuture<java.lang.Void> remove​(@Nullable
                                                                      java.lang.String keyFamily,
                                                                      @NonNull
                                                                      KeyT key)
        Unconditionally removes a Key from this Table Segment. If the Key does not exist, no action will be taken.
        Parameters:
        keyFamily - (Optional) The Key Family for the Key to remove.
        key - The Key to remove.
        Returns:
        A CompletableFuture that, when completed, will indicate the Key has been removed.
      • remove

        java.util.concurrent.CompletableFuture<java.lang.Void> remove​(@Nullable
                                                                      java.lang.String keyFamily,
                                                                      @NonNull
                                                                      KeyT key,
                                                                      @NonNull
                                                                      @NonNull Version version)
        Conditionally Removes a Key from this Table Segment.
        Parameters:
        keyFamily - (Optional) The Key Family for the Key to remove.
        key - The Key to remove.
        version - A Version representing the version that this Key must have in order to remove it.
        Returns:
        A CompletableFuture that, when completed, will indicate the Key has been removed. Notable exceptions:
      • removeAll

        java.util.concurrent.CompletableFuture<java.lang.Void> removeAll​(@Nullable
                                                                         java.lang.String keyFamily,
                                                                         @NonNull
                                                                         @NonNull java.lang.Iterable<TableKey<KeyT>> keys)
        Removes one or more TableKey instances that belong to the same Key Family from this Table Segment. All removals are performed atomically (either all keys or no key will be removed).
        Parameters:
        keyFamily - The Key Family for the TableKey.
        keys - An Iterable of keys to remove. If for at least one such key, TableKey.getVersion() indicates a conditional update, this will perform an atomic Conditional Remove conditioned on the server-side versions matching the provided ones (for all TableKey instances that have one); otherwise an Unconditional Remove will be performed. See KeyValueTable doc for more details on Types of Updates.
        Returns:
        A CompletableFuture that, when completed, will indicate that the keys have been removed. Notable exceptions:
      • get

        java.util.concurrent.CompletableFuture<TableEntry<KeyT,​ValueT>> get​(@Nullable
                                                                                  java.lang.String keyFamily,
                                                                                  @NonNull
                                                                                  KeyT key)
        Gets the latest value for the a Key that belong to a specific Key Family.
        Parameters:
        keyFamily - (Optional) The Key Family for the Key to get.
        key - The Key to get the value for.
        Returns:
        A CompletableFuture that, when completed, will contain the requested result. If no such Key exists, this will be completed with a null value.
      • getAll

        java.util.concurrent.CompletableFuture<java.util.List<TableEntry<KeyT,​ValueT>>> getAll​(@Nullable
                                                                                                     java.lang.String keyFamily,
                                                                                                     @NonNull
                                                                                                     @NonNull java.lang.Iterable<KeyT> keys)
        Gets the latest values for a set of Keys that do belong to the same Key Family.
        Parameters:
        keyFamily - (Optional) The Key Family for all requested Keys.
        keys - An Iterable of Keys to get values for.
        Returns:
        A CompletableFuture that, when completed, will contain a List of TableEntry instances for the requested keys. The size of the list will be the same as keys.size() and the results will be in the same order as the requested keys. Any keys which do not have a value will have a null entry at their index.
      • keyIterator

        io.pravega.common.util.AsyncIterator<IteratorItem<TableKey<KeyT>>> keyIterator​(@NonNull
                                                                                       @NonNull java.lang.String keyFamily,
                                                                                       int maxKeysAtOnce,
                                                                                       @Nullable
                                                                                       IteratorState state)
        Creates a new Iterator over all the TableKeys in this KeyValueTable that belong to a specific Key Family.
        Parameters:
        keyFamily - The Key Family for which to iterate over keys.
        maxKeysAtOnce - The maximum number of TableKeys to return with each call to AsyncIterator.getNext().
        state - (Optional) An IteratorState that represents a continuation token that can be used to resume a previously interrupted iteration. This can be obtained by invoking IteratorItem.getState(). A null value will create an iterator that lists all keys.
        Returns:
        An AsyncIterator that can be used to iterate over all the Keys in this KeyValueTable that belong to a specific Key Family.
      • entryIterator

        io.pravega.common.util.AsyncIterator<IteratorItem<TableEntry<KeyT,​ValueT>>> entryIterator​(@NonNull
                                                                                                        @NonNull java.lang.String keyFamily,
                                                                                                        int maxEntriesAtOnce,
                                                                                                        @Nullable
                                                                                                        IteratorState state)
        Creates a new Iterator over all the TableEntry instances in this KeyValueTable that belong to a specific Key Family.
        Parameters:
        keyFamily - The Key Family for which to iterate over entries.
        maxEntriesAtOnce - The maximum number of TableEntry instances to return with each call to AsyncIterator.getNext().
        state - (Optional) An IteratorState that represents a continuation token that can be used to resume a previously interrupted iteration. This can be obtained by invoking IteratorItem.getState(). A null value will create an iterator that lists all entries.
        Returns:
        An AsyncIterator that can be used to iterate over all the Entries in this KeyValueTable that belong to a specific Key Family.
      • close

        void close()
        Closes the KeyValueTable. No more updates, removals, retrievals or iterators may be performed using it.
        Specified by:
        close in interface java.lang.AutoCloseable
        See Also:
        AutoCloseable.close()
      • getMapFor

        KeyValueTableMap<KeyT,​ValueT> getMapFor​(@Nullable
                                                      java.lang.String keyFamily)
        Exposes this KeyValueTable instance as a Map. Please refer to the KeyValueTableMap documentation for special cases and limitations.

        This is useful for integrating code that expects to deal with a Map. Not all the KeyValueTable functionality can be implemented using a Map, however the Map interface is fully implemented.

        Parameters:
        keyFamily - (Optional) The Key Family to create the KeyValueTableMap for. Any operations on the returned KeyValueTableMap will only affect this Key Family. If no Key Family is provided (null), then certain KeyValueTableMap APIs may not be supported. Refer to KeyValueTableMap documentation for more details.
        Returns:
        A new KeyValueTableMap instance bound to this KeyValueTable and Key Family.