com.gemstone.gemfire.internal.process.ControlFileWatchdog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0
*
* 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. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.internal.process;
import java.io.File;
import java.io.IOException;
/**
* Invokes a ControlRequestHandler when a control file has been created.
*
* @author Kirk Lund
* @since 8.0
*/
final class ControlFileWatchdog implements Runnable {
private static final long STOP_TIMEOUT_MILLIS = 60*1000;
private static final long SLEEP_MILLIS = 1000;
private final File workingDir;
private final File file;
private final ControlRequestHandler requestHandler;
private final boolean stopAfterRequest;
private Thread thread;
private boolean alive;
ControlFileWatchdog(final File workingDir, final String fileName, final ControlRequestHandler requestHandler, final boolean stopAfterRequest) {
this.workingDir = workingDir;
this.file = new File(this.workingDir, fileName);
this.requestHandler = requestHandler;
this.stopAfterRequest = stopAfterRequest;
}
@Override
public void run() {
try { // always set this.alive before stopping
while (isAlive()) {
try { // handle handle exceptions
Thread.sleep(SLEEP_MILLIS);
if (this.file.exists()) {
try { // always check stopAfterRequest after main work
work();
} finally {
if (this.stopAfterRequest) {
stopMe();
}
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// allow to loop around and check isAlive()
} catch (IOException e) {
ControllableProcess.getOrCreateLogWriter().error("Unable to control process with " + this.file + ". Please add tools.jar from JDK to classpath for improved process control.");
// allow to loop around and check isAlive()
}
}
} finally {
synchronized (this) {
this.alive = false;
}
}
}
private void work() throws IOException {
try { // always delete file after invoking handler
this.requestHandler.handleRequest();
} finally {
try {
this.file.delete();
} catch (SecurityException e) {
ControllableProcess.getOrCreateLogWriter().warning("Unable to delete " + this.file, e);
}
}
}
void start() {
synchronized (this) {
if (this.thread == null) {
this.thread = new Thread(this, createThreadName());
this.thread.setDaemon(true);
this.alive = true;
this.thread.start();
}
}
}
void stop() throws InterruptedException {
Thread stopping = null;
synchronized (this) {
if (this.thread != null) {
this.alive = false;
if (this.thread != Thread.currentThread()) {
this.thread.interrupt();
stopping = this.thread;
}
this.thread = null;
}
}
if (stopping != null) {
stopping.join(STOP_TIMEOUT_MILLIS);
}
}
boolean isAlive() {
synchronized (this) {
return this.alive;
}
}
private void stopMe() {
synchronized (this) {
if (this.thread != null) {
this.alive = false;
this.thread = null;
}
}
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
sb.append("@").append(System.identityHashCode(this)).append("{");
sb.append("workingDir=").append(this.workingDir);
sb.append(", file=").append(this.file);
sb.append(", alive=").append(this.alive);
sb.append(", stopAfterRequest=").append(this.stopAfterRequest);
return sb.append("}").toString();
}
private String createThreadName() {
return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + " monitoring " + this.file.getName();
}
/**
* Defines the callback to be invoked when the control file exists.
*/
interface ControlRequestHandler {
public void handleRequest() throws IOException;
}
}