Search in sources :

Example 1 with FilteringDispatcher

use of org.apache.jackrabbit.oak.plugins.observation.FilteringDispatcher in project jackrabbit-oak by apache.

the class ChangeProcessor method createObserver.

private FilteringObserver createObserver(final WhiteboardExecutor executor) {
    FilteringDispatcher fd = new FilteringDispatcher(this);
    BackgroundObserver bo = new BackgroundObserver(fd, executor, queueLength) {

        private volatile long delay;

        private volatile boolean blocking;

        private long lastQueueFullWarnTimestamp = -1;

        @Override
        protected void added(int newQueueSize) {
            queueSizeChanged(newQueueSize);
        }

        @Override
        protected void removed(int newQueueSize, long created) {
            queueSizeChanged(newQueueSize);
        }

        private void queueSizeChanged(int newQueueSize) {
            maxQueueLengthRecorder.recordValue(newQueueSize);
            tracker.recordQueueLength(newQueueSize);
            if (newQueueSize >= queueLength) {
                if (commitRateLimiter != null) {
                    if (!blocking) {
                        logQueueFullWarning("Revision queue is full. Further commits will be blocked.");
                    }
                    commitRateLimiter.blockCommits();
                } else if (!blocking) {
                    logQueueFullWarning("Revision queue is full. Further revisions will be compacted.");
                }
                blocking = true;
            } else {
                double fillRatio = (double) newQueueSize / queueLength;
                if (fillRatio > DELAY_THRESHOLD) {
                    if (commitRateLimiter != null) {
                        if (delay == 0) {
                            LOG.warn("Revision queue is becoming full. Further commits will be delayed.");
                        }
                        // Linear backoff proportional to the number of items exceeding
                        // DELAY_THRESHOLD. Offset by 1 to trigger the log message in the
                        // else branch once the queue falls below DELAY_THRESHOLD again.
                        int newDelay = 1 + (int) ((fillRatio - DELAY_THRESHOLD) / (1 - DELAY_THRESHOLD) * MAX_DELAY);
                        if (newDelay > delay) {
                            delay = newDelay;
                            commitRateLimiter.setDelay(delay);
                        }
                    }
                } else {
                    if (commitRateLimiter != null) {
                        if (delay > 0) {
                            LOG.debug("Revision queue becoming empty. Unblocking commits");
                            commitRateLimiter.setDelay(0);
                            delay = 0;
                        }
                        if (blocking) {
                            LOG.debug("Revision queue becoming empty. Stop delaying commits.");
                            commitRateLimiter.unblockCommits();
                            blocking = false;
                        }
                    } else {
                        blocking = false;
                    }
                }
            }
        }

        private void logQueueFullWarning(String message) {
            long currTime = clock.getTime();
            if (lastQueueFullWarnTimestamp + QUEUE_FULL_WARN_INTERVAL < currTime) {
                LOG.warn("{} Suppressing further such cases for {} minutes.", message, TimeUnit.MILLISECONDS.toMinutes(QUEUE_FULL_WARN_INTERVAL));
                lastQueueFullWarnTimestamp = currTime;
            } else {
                LOG.debug(message);
            }
        }

        @Override
        public String toString() {
            return "Prefiltering BackgroundObserver for " + ChangeProcessor.this;
        }
    };
    return new FilteringObserver(bo, new Filter() {

        @Override
        public boolean excludes(NodeState root, CommitInfo info) {
            final FilterResult filterResult = evalPrefilter(root, info, getChangeSet(info));
            switch(filterResult) {
                case PREFILTERING_SKIPPED:
                    {
                        prefilterSkipCount++;
                        return false;
                    }
                case EXCLUDE:
                    {
                        prefilterExcludeCount++;
                        return true;
                    }
                case INCLUDE:
                    {
                        prefilterIncludeCount++;
                        return false;
                    }
                default:
                    {
                        LOG.info("isExcluded: unknown/unsupported filter result: " + filterResult);
                        prefilterSkipCount++;
                        return false;
                    }
            }
        }
    });
}
Also used : BackgroundObserver(org.apache.jackrabbit.oak.spi.commit.BackgroundObserver) NodeState(org.apache.jackrabbit.oak.spi.state.NodeState) FilteringDispatcher(org.apache.jackrabbit.oak.plugins.observation.FilteringDispatcher) EventFilter(org.apache.jackrabbit.oak.plugins.observation.filter.EventFilter) ChangeSetFilter(org.apache.jackrabbit.oak.plugins.observation.filter.ChangeSetFilter) Filter(org.apache.jackrabbit.oak.plugins.observation.Filter) FilteringObserver(org.apache.jackrabbit.oak.plugins.observation.FilteringObserver) CommitInfo(org.apache.jackrabbit.oak.spi.commit.CommitInfo)

Aggregations

Filter (org.apache.jackrabbit.oak.plugins.observation.Filter)1 FilteringDispatcher (org.apache.jackrabbit.oak.plugins.observation.FilteringDispatcher)1 FilteringObserver (org.apache.jackrabbit.oak.plugins.observation.FilteringObserver)1 ChangeSetFilter (org.apache.jackrabbit.oak.plugins.observation.filter.ChangeSetFilter)1 EventFilter (org.apache.jackrabbit.oak.plugins.observation.filter.EventFilter)1 BackgroundObserver (org.apache.jackrabbit.oak.spi.commit.BackgroundObserver)1 CommitInfo (org.apache.jackrabbit.oak.spi.commit.CommitInfo)1 NodeState (org.apache.jackrabbit.oak.spi.state.NodeState)1