|
@@ -24,8 +24,9 @@ import java.util.Objects;
|
|
|
import java.util.Set;
|
|
|
|
|
|
/**
|
|
|
- * Opts out of the query cache if field level security is active for the current request,
|
|
|
- * and its unsafe to cache.
|
|
|
+ * Opts out of the query cache if field level security is active for the current request, and it is unsafe to cache. Note that the method
|
|
|
+ * {@link #listenForLicenseStateChanges()} must be invoked after construction of the query cache and before any other public methods are
|
|
|
+ * invoked on this query cache.
|
|
|
*/
|
|
|
public final class OptOutQueryCache extends AbstractIndexComponent implements LicenseStateListener, QueryCache {
|
|
|
|
|
@@ -33,6 +34,7 @@ public final class OptOutQueryCache extends AbstractIndexComponent implements Li
|
|
|
private final ThreadContext context;
|
|
|
private final String indexName;
|
|
|
private final XPackLicenseState licenseState;
|
|
|
+ private volatile boolean licenseStateListenerRegistered;
|
|
|
|
|
|
public OptOutQueryCache(
|
|
|
final IndexSettings indexSettings,
|
|
@@ -44,28 +46,46 @@ public final class OptOutQueryCache extends AbstractIndexComponent implements Li
|
|
|
this.context = Objects.requireNonNull(context, "threadContext must not be null");
|
|
|
this.indexName = indexSettings.getIndex().getName();
|
|
|
this.licenseState = Objects.requireNonNull(licenseState, "licenseState");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Register this query cache to listen for license state changes. This must be done after construction of this query cache before any
|
|
|
+ * other public methods are invoked on this query cache.
|
|
|
+ */
|
|
|
+ public void listenForLicenseStateChanges() {
|
|
|
+ /*
|
|
|
+ * Registering this as a listener can not be done in the constructor because otherwise it would be unsafe publication of this. That
|
|
|
+ * is, it would expose this to another thread before the constructor had finished. Therefore, we have a dedicated method to register
|
|
|
+ * the listener that is invoked after the constructor has returned.
|
|
|
+ */
|
|
|
+ assert licenseStateListenerRegistered == false;
|
|
|
licenseState.addListener(this);
|
|
|
+ licenseStateListenerRegistered = true;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void close() throws ElasticsearchException {
|
|
|
+ assert licenseStateListenerRegistered;
|
|
|
licenseState.removeListener(this);
|
|
|
clear("close");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void licenseStateChanged() {
|
|
|
+ assert licenseStateListenerRegistered;
|
|
|
clear("license state changed");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void clear(String reason) {
|
|
|
+ public void clear(final String reason) {
|
|
|
+ assert licenseStateListenerRegistered;
|
|
|
logger.debug("full cache clear, reason [{}]", reason);
|
|
|
indicesQueryCache.clearIndex(index().getName());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public Weight doCache(Weight weight, QueryCachingPolicy policy) {
|
|
|
+ assert licenseStateListenerRegistered;
|
|
|
if (licenseState.isAuthAllowed() == false) {
|
|
|
logger.debug("not opting out of the query cache; authorization is not allowed");
|
|
|
return indicesQueryCache.doCache(weight, policy);
|