Interface TransactionScopedCache

  • All Known Implementing Classes:
    NoOpTransactionScopedCache, ReadOnlyTransactionScopedCache

    public interface TransactionScopedCache
    The LockWatchValueScopingCache will provide one of these to every (relevant) transaction, and this will contain a view of the cache at the correct point in time, which is determined by the transaction's LockWatchVersion. The semantics of this cache are as follows: 1. Writes in the transaction will invalidate values in this local cache (but *not* in the central cache, as the lock events will take care of that); 2. Reads will first try to read a value from the cache; if not present, it will be loaded remotely and cached locally. 3. At commit time, all remote reads will be flushed to the central cache (and these reads will be filtered based on the lock events that have happened since the transaction was started). It is safe to perform these reads due to the transaction semantics: for a serialisable transaction, we will use the locked descriptors at commit time to validate whether we have read-write conflicts; otherwise, reading the values in the cache is just as safe as reading a snapshot of the database taken at the start timestamp.
    • Method Detail

      • get

        Map<Cell,​byte[]> get​(TableReference tableReference,
                                   Set<Cell> cells,
                                   java.util.function.Function<Set<Cell>,​com.google.common.util.concurrent.ListenableFuture<Map<Cell,​byte[]>>> valueLoader)
        This should be used for performing *synchronous* gets. The reason the value loader function returns a listenable future is to optimise parallel requests to the cache: only the code that directly affects the state of the cache is synchronised, while loads from the database are done outside synchronised blocks.
      • getAsync

        com.google.common.util.concurrent.ListenableFuture<Map<Cell,​byte[]>> getAsync​(TableReference tableReference,
                                                                                            Set<Cell> cells,
                                                                                            java.util.function.Function<Set<Cell>,​com.google.common.util.concurrent.ListenableFuture<Map<Cell,​byte[]>>> valueLoader)
      • getRows

        NavigableMap<byte[],​RowResult<byte[]>> getRows​(TableReference tableRef,
                                                             Iterable<byte[]> rows,
                                                             ColumnSelection columnSelection,
                                                             java.util.function.Function<Set<Cell>,​Map<Cell,​byte[]>> cellLoader,
                                                             java.util.function.Function<Iterable<byte[]>,​NavigableMap<byte[],​RowResult<byte[]>>> rowLoader)
        The cache will try to fulfil as much of the request as possible with cached values. In the case where some of the columns are present in the cache for a row, the cellLoader will be used to read the remaining cells remotely. For rows that have none of the columns present in the cache, the rowLoader will be used. Note that this may result in two KVS reads, but it is expected to be offset by not having to read the already cached values. The result map uses UnsignedBytes.lexicographicalComparator() on the keys, so there will be no duplicate rows, even if duplicates were specified in rows. Any row with no columns present will be absent in the result map, as long as the rowLoader behaves in the same way.
      • finalise

        void finalise()
        This method should be called before retrieving the value or hit digest, as it guarantees that no more reads or writes will be performed on the cache. This method is idempotent, and may legitimately be called multiple times.
      • createReadOnlyCache

        TransactionScopedCache createReadOnlyCache​(com.palantir.lock.watch.CommitUpdate commitUpdate)