Class AbstractLazyLoadRunMap<R>

java.lang.Object
java.util.AbstractMap<Integer,R>
jenkins.model.lazy.AbstractLazyLoadRunMap<R>
All Implemented Interfaces:
Map<Integer,R>, SortedMap<Integer,R>
Direct Known Subclasses:
RunMap

public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer,R> implements SortedMap<Integer,R>
SortedMap that keeps build records by their build numbers, in the descending order (newer ones first.)

The main thing about this class is that it encapsulates the lazy loading logic. That is, while this class looks and feels like a normal SortedMap from outside, it actually doesn't have every item in the map instantiated yet. As items in the map get requested, this class retrieves them on demand, one by one.

The lookup is done by using the build number as the key (hence the key type is Integer).

This class makes the following assumption about the on-disk layout of the data:

  • Every build is stored in a directory, named after its number.

Some of the SortedMap operations are weakly implemented. For example, AbstractMap.size() may be inaccurate because we only count the number of directories that look like build records, without checking if they are loadable. But these weaknesses aren't distinguishable from concurrent modifications, where another thread deletes a build while one thread iterates them.

Some of the SortedMap operations are inefficiently implemented, by loading all the build records eagerly. We hope to replace these implementations by more efficient lazy-loading ones as we go.

Object lock of this is used to make sure mutation occurs sequentially. That is, ensure that only one thread is actually calling retrieve(File) and updating AbstractLazyLoadRunMap.Index.byNumber.

Since:
1.485
Author:
Kohsuke Kawaguchi
  • Field Details

    • dir

      protected File dir
      Base directory for data. In effect this is treated as a final field, but can't mark it final because the compatibility requires that we make it settable in the first call after the constructor.
  • Constructor Details

    • AbstractLazyLoadRunMap

      @Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) protected AbstractLazyLoadRunMap()
  • Method Details

    • keySet

      public Set<Integer> keySet()
      Specified by:
      keySet in interface Map<Integer,R>
      Specified by:
      keySet in interface SortedMap<Integer,R>
      Overrides:
      keySet in class AbstractMap<Integer,R>
    • values

      public Collection<R> values()
      Specified by:
      values in interface Map<Integer,R>
      Specified by:
      values in interface SortedMap<Integer,R>
      Overrides:
      values in class AbstractMap<Integer,R>
    • initBaseDir

      @Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) protected void initBaseDir(File dir)
    • baseDirInitialized

      @Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) public final boolean baseDirInitialized()
      Returns:
      true if AbstractLazyLoadRunMap() was called with a non-null param, or RunMap.load(Job, RunMap.Constructor) was called
    • updateBaseDir

      public final void updateBaseDir(File dir)
      Updates base directory location after directory changes. This method should be used on jobs renaming, etc.
      Parameters:
      dir - Directory location
      Since:
      1.546
    • purgeCache

      public void purgeCache()
      Let go of all the loaded references. This is a bit more sophisticated version of forcing GC. Primarily for debugging and testing lazy loading behaviour.
      Since:
      1.507
    • allowLoad

      @Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) protected boolean allowLoad(int buildNumber)
    • recognizeNumber

      @Restricted(org.kohsuke.accmod.restrictions.Beta.class) public final void recognizeNumber(int buildNumber)
      Permits a previous blocked build number to be eligible for loading.
      Parameters:
      buildNumber - a build number
      See Also:
    • comparator

      public Comparator<? super Integer> comparator()
      Specified by:
      comparator in interface SortedMap<Integer,R>
    • isEmpty

      public boolean isEmpty()
      Specified by:
      isEmpty in interface Map<Integer,R>
      Overrides:
      isEmpty in class AbstractMap<Integer,R>
    • entrySet

      public Set<Map.Entry<Integer,R>> entrySet()
      Specified by:
      entrySet in interface Map<Integer,R>
      Specified by:
      entrySet in interface SortedMap<Integer,R>
      Specified by:
      entrySet in class AbstractMap<Integer,R>
    • getLoadedBuilds

      public SortedMap<Integer,R> getLoadedBuilds()
      Returns a read-only view of records that has already been loaded.
    • subMap

      public SortedMap<Integer,R> subMap(Integer fromKey, Integer toKey)
      Specified by:
      subMap in interface SortedMap<Integer,R>
      Parameters:
      fromKey - Biggest build number to be in the returned set.
      toKey - Smallest build number-1 to be in the returned set (-1 because this is exclusive)
    • headMap

      public SortedMap<Integer,R> headMap(Integer toKey)
      Specified by:
      headMap in interface SortedMap<Integer,R>
    • tailMap

      public SortedMap<Integer,R> tailMap(Integer fromKey)
      Specified by:
      tailMap in interface SortedMap<Integer,R>
    • firstKey

      public Integer firstKey()
      Specified by:
      firstKey in interface SortedMap<Integer,R>
    • lastKey

      public Integer lastKey()
      Specified by:
      lastKey in interface SortedMap<Integer,R>
    • newestBuild

      public R newestBuild()
    • oldestBuild

      public R oldestBuild()
    • get

      public R get(Object key)
      Specified by:
      get in interface Map<Integer,R>
      Overrides:
      get in class AbstractMap<Integer,R>
    • get

      public R get(int n)
    • runExists

      public boolean runExists(int number)
      Checks if the specified build exists.
      Parameters:
      number - the build number to probe.
      Returns:
      true if there is an run for the corresponding number, note that this does not mean that the corresponding record will load.
      Since:
      2.14
    • search

      @CheckForNull public R search(int n, AbstractLazyLoadRunMap.Direction d)
      Finds the build #M where M is nearby the given 'n'.
      Parameters:
      n - the index to start the search from
      d - defines what we mean by "nearby" above. If EXACT, find #N or return null. If ASC, finds the closest #M that satisfies M ≥ N. If DESC, finds the closest #M that satisfies M ≤ N.
    • getById

      public R getById(String id)
    • getByNumber

      public R getByNumber(int n)
    • maxNumberOnDisk

      @Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) public int maxNumberOnDisk()
      Returns:
      the highest recorded build number, or 0 if there are none
    • proposeNewNumber

      protected final void proposeNewNumber(int number) throws IllegalStateException
      Throws:
      IllegalStateException
    • put

      public R put(R value)
    • _put

      protected R _put(R value)
    • put

      public R put(Integer key, R r)
      Specified by:
      put in interface Map<Integer,R>
      Overrides:
      put in class AbstractMap<Integer,R>
    • putAll

      public void putAll(Map<? extends Integer,? extends R> rhs)
      Specified by:
      putAll in interface Map<Integer,R>
      Overrides:
      putAll in class AbstractMap<Integer,R>
    • getNumberOf

      protected abstract int getNumberOf(R r)
      Subtype to provide Run.getNumber() so that this class doesn't have to depend on it.
    • getIdOf

      protected String getIdOf(R r)
      Subtype to provide Run.getId() so that this class doesn't have to depend on it.
    • createReference

      protected BuildReference<R> createReference(R r)
      Allow subtype to capture a reference.
    • retrieve

      protected abstract R retrieve(File dir) throws IOException
      Parses R instance from data in the specified directory.
      Returns:
      null if the parsing failed.
      Throws:
      IOException - if the parsing failed. This is just like returning null except the caller will catch the exception and report it.
    • removeValue

      public boolean removeValue(R run)
    • reset

      public void reset(TreeMap<Integer,R> builds)
      Replaces all the current loaded Rs with the given ones.
    • hashCode

      public int hashCode()
      Specified by:
      hashCode in interface Map<Integer,R>
      Overrides:
      hashCode in class AbstractMap<Integer,R>
    • equals

      public boolean equals(Object o)
      Specified by:
      equals in interface Map<Integer,R>
      Overrides:
      equals in class AbstractMap<Integer,R>