DenyAclCollector.java
/*
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.elasticsearch.index.rebuild;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Collects the identifiers of objects whose ACL contains deny rules, so that an index rebuild can
* report them once at the end instead of logging a line per entry.
*
* <p>The search index cannot express denial, so such entries are dropped when an object is indexed.
* That is worth telling an administrator about, but the per-entry message it used to produce fired
* once per deny entry per object and drowned the rebuild log.
*
* <p>Collection is only active between {@link #start()} and {@link #stop()}, which
* {@link IndexRebuildService} brackets a rebuild with. Outside a rebuild — during ordinary
* indexing — {@link #record} does nothing beyond a volatile read, so nothing accumulates in a
* long-running instance.
*
* <p>State is held per thread. A rebuild runs on the thread that called it, and keeping the
* collected ids thread-local means concurrent ordinary indexing on other threads cannot add to a
* rebuild's report, nor can two rebuilds interfere.
*/
public final class DenyAclCollector {
/** Ids collected for the rebuild running on this thread, or null when no rebuild is running. */
private static final ThreadLocal<Set<String>> COLLECTED = new ThreadLocal<>();
private DenyAclCollector() {
}
/**
* Start collecting on the current thread, discarding anything previously collected.
*/
public static void start() {
COLLECTED.set(new LinkedHashSet<>());
}
/**
* Note that the object with the given identifier carries at least one deny entry. Does nothing
* when no rebuild is running on this thread.
*
* @param identifier
* the identifier of the event or series, may be null
*/
public static void record(String identifier) {
Set<String> collected = COLLECTED.get();
if (collected != null && identifier != null) {
collected.add(identifier);
}
}
/**
* Return the identifiers collected on this thread, in encounter order.
*
* @return the identifiers, empty if no rebuild is running
*/
public static Set<String> collected() {
Set<String> collected = COLLECTED.get();
return collected == null ? Collections.emptySet() : Collections.unmodifiableSet(collected);
}
/**
* Stop collecting on the current thread and release the collected identifiers.
*/
public static void stop() {
COLLECTED.remove();
}
}