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

org.neo4j.kernel.lifecycle.SafeLifecycle Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.kernel.lifecycle;

import static org.neo4j.kernel.lifecycle.LifecycleStatus.NONE;
import static org.neo4j.kernel.lifecycle.LifecycleStatus.SHUTDOWN;
import static org.neo4j.kernel.lifecycle.LifecycleStatus.STARTED;
import static org.neo4j.kernel.lifecycle.LifecycleStatus.STOPPED;

/**
 * A safer lifecycle adapter with strict semantics and as
 * a result simpler error handling and reasoning. If the
 * semantics of this class is not consistent with what you
 * are after, then it is probably better to create a new
 * adapter with the specific semantics required.
 * 
 * Guide
 *
 *  *: No-op    (will not invoke operation)
 *  -: Error    (will throw IllegalStateException)
 *
 *  NONE:       ("pre initialization")
 *  STOPPED:    ("initialized" or "stopped")
 *  STARTED:    ("started")
 *  SHUTDOWN:   ("shutdown")
 * 
* A successful operation is an operation not throwing an exception. *

* End states on a successful operation. *

 * +----------+---------+---------+------------+-------------+
 * | FROM \op | init()  | start() |   stop()   | shutdown()  |
 * +----------+---------+---------+------------+-------------+
 * | NONE     | STOPPED | -       | -          | NONE(*)     |
 * | STOPPED  | -       | STARTED | STOPPED(*) | SHUTDOWN    |
 * | STARTED  | -       | -       | STOPPED    | -           |
 * | SHUTDOWN | -       | -       | -          | -           |
 * +----------+---------+---------+------------+-------------+
 * 
* End states on a failed operation. *
 *+----------+---------+---------+------------+-------------+
 * | FROM \op | init()  | start() |   stop()   | shutdown()  |
 * +----------+---------+---------+------------+-------------+
 * | NONE     | STOPPED | -       | -          | NONE(*)     |
 * | STOPPED  | -       | STOPPED | STOPPED(*) | SHUTDOWN    |
 * | STARTED  | -       | -       | STOPPED    | -           |
 * | SHUTDOWN | -       | -       | -          | -           |
 * +----------+---------+---------+------------+-------------+
 * 
* A few notes: *
    *
  • will not invoke stop0() if start0() wasn't successful
  • *
  • will not invoke shutdown0() if init0() wasn't successful
  • *
* The expectation with regards to error handling and cleanup is that * an unclean start() is cleaned up by the start0() method and thus * the component is left in STOPPED. The same goes for issues happening * during init0(). *

* Because of the way that {@link LifeSupport} operates today, this * class will ignore stop() calls made while in STOPPED. Similarly, calls * to shutdown() will be ignored while in NONE. This allows this class * to be managed by a {@link LifeSupport} without throwing * {@link IllegalStateException} on those state transitions, which * otherwise would have been disallowed and handled in the same way * as other illegal state transitions. *

* This adapter will not allow a shutdown lifecycle to be reinitialized * and started again. */ public abstract class SafeLifecycle implements Lifecycle, LifecycleStatusProvider { private volatile LifecycleStatus state; protected SafeLifecycle() { this(NONE); } SafeLifecycle(LifecycleStatus state) { this.state = state; } /** * @param expected The expected from state. * @param to The to state. * @param op The state transition operation. * @param force Causes the state to be updated regardless of if the operation throws. */ private void transition(LifecycleStatus expected, LifecycleStatus to, Operation op, boolean force) throws Exception { if (state != expected) { throw new IllegalStateException(String.format("Expected %s but was %s", expected, state)); } if (force) { state = to; op.run(); } else { op.run(); state = to; } } @Override public final synchronized void init() throws Exception { transition(NONE, STOPPED, this::init0, false); } @Override public final synchronized void start() throws Exception { transition(STOPPED, STARTED, this::start0, false); } @Override public final synchronized void stop() throws Exception { if (state == STOPPED) { return; } transition(STARTED, STOPPED, this::stop0, true); } @Override public final synchronized void shutdown() throws Exception { if (state == NONE) { state = NONE; return; } transition(STOPPED, SHUTDOWN, this::shutdown0, true); } public void init0() throws Exception {} public void start0() throws Exception {} public void stop0() throws Exception {} public void shutdown0() throws Exception {} @Override public LifecycleStatus getStatus() { return state; } interface Operation { void run() throws Exception; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy