All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.plugin.ServerStatus Maven / Gradle / Ivy

There is a newer version: 2.0.0-alpha.3
Show newest version
/**
 * The MIT License
 * Copyright (c) 2012 Graylog, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.graylog2.plugin;

import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.Uninterruptibles;
import org.graylog2.plugin.lifecycles.Lifecycle;
import org.graylog2.plugin.system.NodeId;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

@Singleton
public class ServerStatus {
    private static final Logger LOG = LoggerFactory.getLogger(ServerStatus.class);

    public MessageDetailRecordingStrategy getDetailedMessageRecordingStrategy() {
        return messageDetailRecordingStrategy;
    }

    public enum Capability {
        SERVER,
        RADIO,
        MASTER,
        LOCALMODE
    }

    private final EventBus eventBus;
    private final NodeId nodeId;
    private final DateTime startedAt;
    private final Set capabilitySet;
    private MessageDetailRecordingStrategy messageDetailRecordingStrategy = MessageDetailRecordingStrategy.NEVER;

    private final AtomicBoolean isProcessing = new AtomicBoolean(false);
    private final AtomicBoolean processingPauseLocked = new AtomicBoolean(false);
    private final CountDownLatch runningLatch = new CountDownLatch(1);

    private volatile Lifecycle lifecycle = Lifecycle.UNINITIALIZED;

    @Inject
    public ServerStatus(BaseConfiguration configuration, Set capabilities, EventBus eventBus) {
        this.eventBus = eventBus;
        this.nodeId = new NodeId(configuration.getNodeIdFile());
        this.startedAt = Tools.iso8601();
        this.capabilitySet = Sets.newHashSet(capabilities); // copy, because we support adding more capabilities later
        this.messageDetailRecordingStrategy = configuration.isMessageRecordingsEnabled()
                ? MessageDetailRecordingStrategy.ALWAYS
                : MessageDetailRecordingStrategy.NEVER;
    }

    public NodeId getNodeId() {
        return nodeId;
    }

    public Lifecycle getLifecycle() {
        return lifecycle;
    }

    private void publishLifecycle(final Lifecycle lifecycle) {
        setLifecycle(lifecycle);
        eventBus.post(lifecycle);
    }

    private void setLifecycle(final Lifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }

    public void initialize() {
        publishLifecycle(Lifecycle.STARTING);
    }

    public void start() {
        isProcessing.set(true);
        runningLatch.countDown();
        publishLifecycle(Lifecycle.RUNNING);
    }

    public void shutdown(boolean forceProcessing) {
        if (forceProcessing) {
            unlockProcessingPause();
            isProcessing.set(true);
        }

        publishLifecycle(Lifecycle.HALTING);
    }

    public void shutdown() {
        shutdown(true);
    }

    public void fail() {
        isProcessing.set(false);
        publishLifecycle(Lifecycle.FAILED);
    }

    public void overrideLoadBalancerDead() {
        publishLifecycle(Lifecycle.OVERRIDE_LB_DEAD);
    }

    public void overrideLoadBalancerAlive() {
        publishLifecycle(Lifecycle.OVERRIDE_LB_ALIVE);
    }

    public void awaitRunning(final Runnable runnable) {
        LOG.debug("Waiting for server to enter RUNNING state");
        Uninterruptibles.awaitUninterruptibly(runningLatch);
        LOG.debug("Server entered RUNNING state");

        try {
            LOG.debug("Executing awaitRunning callback");
            runnable.run();
        } catch (Exception e) {
            LOG.error("awaitRunning callback failed", e);
        }
    }

    public DateTime getStartedAt() {
        return startedAt;
    }

    public DateTimeZone getTimezone() {
        return DateTimeZone.getDefault();
    }

    public ServerStatus addCapability(Capability capability) {
        this.capabilitySet.add(capability);
        return this;
    }

    public ServerStatus addCapabilities(Capability... capabilities) {
        this.capabilitySet.addAll(Arrays.asList(capabilities));
        return this;
    }

    public boolean hasCapability(Capability capability) {
        return this.capabilitySet.contains(capability);
    }

    public boolean hasCapabilities(Capability... capabilities) {
        return this.capabilitySet.containsAll(Arrays.asList(capabilities));
    }

    public boolean isProcessing() {
        return isProcessing.get();
    }

    public void pauseMessageProcessing() {
        pauseMessageProcessing(true);
    }

    public void pauseMessageProcessing(boolean locked) {
        // Never override pause lock if already locked.
        processingPauseLocked.compareAndSet(false, locked);
        isProcessing.set(false);

        publishLifecycle(Lifecycle.PAUSED);
    }

    public void resumeMessageProcessing() throws ProcessingPauseLockedException {
        if (processingPauseLocked()) {
            throw new ProcessingPauseLockedException("Processing pause is locked. Wait until the locking task has finished " +
                    "or manually unlock if you know what you are doing.");
        }

        start();
    }

    public boolean processingPauseLocked() {
        return processingPauseLocked.get();
    }

    public void unlockProcessingPause() {
        processingPauseLocked.set(false);
    }

    private ServerStatus removeCapability(Capability capability) {
        this.capabilitySet.remove(capability);
        return this;
    }

    public void setLocalMode(boolean localMode) {
        if (localMode) {
            addCapability(Capability.LOCALMODE);
        } else {
            removeCapability(Capability.LOCALMODE);
        }
    }

    public enum MessageDetailRecordingStrategy {
        NEVER,
        ALWAYS;

        public boolean shouldRecord(final Message message) {
            switch (this) {
                case NEVER:
                    return false;
                case ALWAYS:
                    return true;
                default:
                    return false;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy