Talk about SingleObjectCache of Elasticsearch.

  elasticsearch

Order

This article mainly studies SingleObjectCache of Elasticsearch.

SingleObjectCache

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/SingleObjectCache.java

public abstract class SingleObjectCache<T>{

    private volatile T cached;
    private Lock refreshLock = new ReentrantLock();
    private final TimeValue refreshInterval;
    protected long lastRefreshTimestamp = 0;

    protected SingleObjectCache(TimeValue refreshInterval, T initialValue) {
        if (initialValue == null) {
            throw new IllegalArgumentException("initialValue must not be null");
        }
        this.refreshInterval = refreshInterval;
        cached = initialValue;
    }


    /**
     * Returns the currently cached object and potentially refreshes the cache before returning.
     */
    public T getOrRefresh() {
        if (needsRefresh()) {
            if(refreshLock.tryLock()) {
                try {
                    if (needsRefresh()) { // check again!
                        cached = refresh();
                        assert cached != null;
                        lastRefreshTimestamp = System.currentTimeMillis();
                    }
                } finally {
                    refreshLock.unlock();
                }
            }
        }
        assert cached != null;
        return cached;
    }

    /** Return the potentially stale cached entry. */
    protected final T getNoRefresh() {
        return cached;
    }

    /**
     * Returns a new instance to cache
     */
    protected abstract T refresh();

    /**
     * Returns <code>true</code> iff the cache needs to be refreshed.
     */
    protected boolean needsRefresh() {
        if (refreshInterval.millis() == 0) {
            return true;
        }
        final long currentTime = System.currentTimeMillis();
        return (currentTime - lastRefreshTimestamp) > refreshInterval.millis();
    }
}
  • SingleObjectCache constructor requires refreshInterval and initialValue parameters; It provides the getOrRefresh method, which determines whether the cached value has expired, calls the refresh method to refresh the value if it has expired, updates lastRefreshTimestamp at the same time, and returns the cached value if it has not expired.

Example

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/monitor/fs/FsService.java

public class FsService {

    private static final Logger logger = LogManager.getLogger(FsService.class);

    private final FsProbe probe;
    private final TimeValue refreshInterval;
    private final SingleObjectCache<FsInfo> cache;
    private final ClusterInfoService clusterInfoService;

    public static final Setting<TimeValue> REFRESH_INTERVAL_SETTING =
        Setting.timeSetting(
            "monitor.fs.refresh_interval",
            TimeValue.timeValueSeconds(1),
            TimeValue.timeValueSeconds(1),
            Property.NodeScope);

    public FsService(final Settings settings, final NodeEnvironment nodeEnvironment, ClusterInfoService clusterInfoService) {
        this.probe = new FsProbe(nodeEnvironment);
        this.clusterInfoService = clusterInfoService;
        refreshInterval = REFRESH_INTERVAL_SETTING.get(settings);
        logger.debug("using refresh_interval [{}]", refreshInterval);
        cache = new FsInfoCache(refreshInterval, stats(probe, null, logger, null));
    }

    public FsInfo stats() {
        return cache.getOrRefresh();
    }

    private static FsInfo stats(FsProbe probe, FsInfo initialValue, Logger logger, @Nullable ClusterInfo clusterInfo) {
        try {
            return probe.stats(initialValue, clusterInfo);
        } catch (IOException e) {
            logger.debug("unexpected exception reading filesystem info", e);
            return null;
        }
    }

    private class FsInfoCache extends SingleObjectCache<FsInfo> {

        private final FsInfo initialValue;

        FsInfoCache(TimeValue interval, FsInfo initialValue) {
            super(interval, initialValue);
            this.initialValue = initialValue;
        }

        @Override
        protected FsInfo refresh() {
            return stats(probe, initialValue, logger, clusterInfoService.getClusterInfo());
        }

    }

}
  • The constructor of FsService uses FsInfoCache to create cache, and its nonparametric stats method executes cache.getorrrefresh (); FsInfoCache inherits SingleObjectCache. Its refresh method calls the stats method, which refreshes the value through Probe. Stats (Initial Value, ClusterInfo)

Summary

SingleObjectCache constructor requires refreshInterval and initialValue parameters; It provides the getOrRefresh method, which determines whether the cached value has expired, calls the refresh method to refresh the value if it has expired, updates lastRefreshTimestamp at the same time, and returns the cached value if it has not expired.

doc