Class FDBReverseDirectoryCache


  • @API(INTERNAL)
    public class FDBReverseDirectoryCache
    extends Object
    A persistent cache providing reverse lookup facilities from the FDB DirectoryLayer. The implementation only supports reverse lookup of the root entries of the directory layer (those * entries returned by DirectoryLayer.list().

    Important note: This cache is intended to be used only to retrieve directory layer entries that are known to exist. An attempt to retrieve a directory layer entry that does not exist will result in a full scan of the directory layer for each such request

    • Field Detail

      • REVERSE_DIRECTORY_CACHE_ENTRY

        public static final String REVERSE_DIRECTORY_CACHE_ENTRY
      • MAX_ROWS_PER_TRANSACTION

        public static final int MAX_ROWS_PER_TRANSACTION
        The default maximum number of directory entries that will be scanned during a lookup within the context of a single transaction, when this limit is hit, a new one will be started before continuing.
        See Also:
        Constant Field Values
      • MAX_MILLIS_PER_TRANSACTION

        public static final long MAX_MILLIS_PER_TRANSACTION
        The maximum number of milliseconds we'll spend scanning the directory during a lookup within the context of a single transaction, when this limit is hit, a new one will be started before continuing.
    • Constructor Detail

      • FDBReverseDirectoryCache

        public FDBReverseDirectoryCache​(@Nonnull
                                        FDBDatabase fdb,
                                        int maxRowsPerTransaction,
                                        long maxMillisPerTransaction)
    • Method Detail

      • getMaxRowsPerTransaction

        public int getMaxRowsPerTransaction()
        The maximum number of rows scanned in the directory during a lookup within the context of a single transaction, when this limit is hit, a new one will be started before continuing. The default value is 10,000. A value that is less than or equal to zero indicates no row limit.
        Returns:
        row limit
      • setMaxRowsPerTransaction

        public void setMaxRowsPerTransaction​(int maxRowsPerTransaction)
      • getMaxMillisPerTransaction

        public long getMaxMillisPerTransaction()
        The maximum number of milliseconds spent scanning the directory during a lookup within the context of a single transaction, when this limit is hit, a new one will be started before continuing. The default value is 3000ms (3 seconds). A value that is less than or equal to zero indicates no time limit.
        Returns:
        time limit
      • setMaxMillisPerTransaction

        public void setMaxMillisPerTransaction​(long maxMillisPerTransaction)
      • getPersistentCacheMissCount

        public long getPersistentCacheMissCount()
        Get the number of reverse lookups in which the persistent cache was found to be missing an entry, resulting in a scan of the directory layer in order to populate the missing entry.
        Returns:
        the number of cache misses
      • getPersistentCacheHitCount

        public long getPersistentCacheHitCount()
        Get the number of reverse lookups in which the lookup could not be satisfied by the in-memory cache but was satisfied by the persistent reverse lookup cache.
        Returns:
        the number of cache hits
      • clearStats

        public void clearStats()
        Clears all of the statistics gathered.
      • getInReverseDirectoryCacheSubspace

        @Nonnull
        public CompletableFuture<Optional<String>> getInReverseDirectoryCacheSubspace​(@Nullable
                                                                                      FDBStoreTimer timer,
                                                                                      @Nonnull
                                                                                      ScopedValue<Long> scopedReverseDirectoryKey)
        Retrieves the name of the directory entry corresponding to the value of that entry in the directory layer. Unlike get(FDBStoreTimer, ScopedValue), only checks the reverse directory cache subspace for the key. This can be useful when populating the reverse directory cache, so that we can test for the presence of an element without performing an expensive directory layer scan whenever a value is missing. When performing a reverse lookup of a value added to a LocatableResolver through normal means, prefer the use of get(FDBStoreTimer, ScopedValue).
        Parameters:
        timer - FDBStoreTimer for collecting metrics
        scopedReverseDirectoryKey - the value of the entry in the directory layer
        Returns:
        an Optional of the key (path) associated with the provided directory layer value, if no such value exists the Optional is empty
      • get

        @Nonnull
        public CompletableFuture<Optional<String>> get​(@Nonnull
                                                       ScopedValue<Long> scopedReverseDirectoryKey)
        Retrieves the name of the directory entry corresponding to the value of that entry in the directory layer. Note that the retrieval and subsequent population of the stored reverse directory takes place within the context of a new transaction, which means (among other things) that an attempt to get() a directory layer entry that was just created within an as-of-yet uncommitted transaction will not be visible and, thus, result in a NoSuchElementException.
        Parameters:
        scopedReverseDirectoryKey - the value of the entry in the directory layer
        Returns:
        an Optional of the key (path) associated with the provided directory layer value, if no such value exists the Optional is empty
      • get

        @Nonnull
        public CompletableFuture<Optional<String>> get​(@Nullable
                                                       FDBStoreTimer timer,
                                                       @Nonnull
                                                       ScopedValue<Long> scopedReverseDirectoryKey)
        Retrieves the name of the directory entry corresponding to the value of that entry in the directory layer. Note that the retrieval and subsequent population of the stored reverse directory takes place within the context of a new transaction, which means (among other things) that an attempt to get() a directory layer entry that was just created within an as-of-yet uncommitted transaction will not be visible and, thus, result in a NoSuchElementException.
        Parameters:
        timer - FDBStoreTimer for collecting metrics
        scopedReverseDirectoryKey - the value of the entry in the directory layer
        Returns:
        an Optional of the key (path) associated with the provided directory layer value, if no such value exists the Optional is empty
      • put

        public CompletableFuture<Void> put​(@Nonnull
                                           FDBRecordContext context,
                                           @Nonnull
                                           ScopedValue<String> pathKey)
        Explicitly add a new entry to the reverse directory cache.
        Parameters:
        context - the transactional context
        pathKey - the name of an entry in the FDB directory, the value of which is retrieved from the directory and explicitly inserted into the reverse directory cache
        Returns:
        a future that performs the action
        Throws:
        NoSuchElementException - will be thrown by this future if the name provided does not exist in the directory layer.
      • putIfNotExists

        public CompletableFuture<Void> putIfNotExists​(@Nonnull
                                                      FDBRecordContext context,
                                                      @Nonnull
                                                      ScopedValue<String> scopedPathString,
                                                      @Nonnull
                                                      Long pathValue)
        Add a new entry to the reverse directory cache if it does not already exist. If an entry already exists for the pathString provided, the value for the key in the RDC will be compared against the pathValue provided and an IllegalStateException will be thrown if they differ. Note that no effort is made to determine if the pathValue actually exists in the directory layer itself!
        Parameters:
        context - the transaction context in which to do the operation
        scopedPathString - the name of the entry within the scoped of an FDB directory layer
        pathValue - the value of the entry that from that FDB directory layer
        Returns:
        a future that performs the action
        Throws:
        IllegalStateException - if the pathkey provided already exists in the reverse directory layer and the pathValue provided does not match that value
      • rebuild

        public void rebuild​(LocatableResolver scope)
        Clears out the persistent reverse directory cache, repopulates it, clears out the in-memory cache and resets cache miss statistics.
        Parameters:
        scope - name to string resolver
      • waitUntilReadyForTesting

        public void waitUntilReadyForTesting()
        Wait for any asynchronous work started at object creation time to complete. This should only be used for tests in order to avoid spurious conflicts.