/***********************************************************************************************************************
*
* Copyright (C) 2010 by the Stratosphere project (http://stratosphere.eu)
*
* 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.
*
**********************************************************************************************************************/
package eu.stratosphere.nephele.checkpointing;
import java.io.File;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import eu.stratosphere.nephele.configuration.GlobalConfiguration;
import eu.stratosphere.nephele.executiongraph.ExecutionVertexID;
import eu.stratosphere.nephele.fs.FileSystem;
import eu.stratosphere.nephele.fs.Path;
import eu.stratosphere.nephele.io.channels.FileBufferManager;
import eu.stratosphere.nephele.util.StringUtils;
public final class CheckpointUtils {
private static final Log LOG = LogFactory.getLog(CheckpointUtils.class);
/**
* The prefix for the name of the file containing the checkpoint meta data.
*/
public static final String METADATA_PREFIX = "checkpoint";
public static final String LOCAL_CHECKPOINT_PATH_KEY = "checkpoint.local.path";
public static final String DISTRIBUTED_CHECKPOINT_PATH_KEY = "checkpoint.distributed.path";
public static final String COMPLETED_CHECKPOINT_SUFFIX = "_final";
private static Path LOCAL_CHECKPOINT_PATH = null;
private static Path DISTRIBUTED_CHECKPOINT_PATH = null;
private static CheckpointMode CHECKPOINT_MODE = null;
private CheckpointUtils() {
}
public static Path getLocalCheckpointPath() {
if (LOCAL_CHECKPOINT_PATH == null) {
String localCheckpointPath = GlobalConfiguration.getString(LOCAL_CHECKPOINT_PATH_KEY, null);
if (localCheckpointPath == null) {
LOCAL_CHECKPOINT_PATH = new Path(new File(System.getProperty("java.io.tmpdir")).toURI());
} else {
LOCAL_CHECKPOINT_PATH = new Path(localCheckpointPath);
}
}
return LOCAL_CHECKPOINT_PATH;
}
public static Path getDistributedCheckpointPath() {
if (DISTRIBUTED_CHECKPOINT_PATH == null) {
final String path = GlobalConfiguration.getString(DISTRIBUTED_CHECKPOINT_PATH_KEY, null);
if (path == null) {
return null;
}
DISTRIBUTED_CHECKPOINT_PATH = new Path(path);
}
return DISTRIBUTED_CHECKPOINT_PATH;
}
public static boolean hasCompleteCheckpointAvailable(final ExecutionVertexID vertexID) {
return checkForCheckpoint(vertexID, COMPLETED_CHECKPOINT_SUFFIX);
}
public static boolean hasPartialCheckpointAvailable(final ExecutionVertexID vertexID) {
if (checkForCheckpoint(vertexID, "_0")) {
return true;
}
return checkForCheckpoint(vertexID, "_part");
}
public static boolean hasLocalCheckpointAvailable(final ExecutionVertexID vertexID) {
try {
Path local = new Path(getLocalCheckpointPath() + Path.SEPARATOR + METADATA_PREFIX + "_" + vertexID
+ "_0");
final FileSystem localFs = local.getFileSystem();
if (localFs.exists(local)) {
return true;
}
local = new Path(getLocalCheckpointPath() + Path.SEPARATOR + METADATA_PREFIX + "_" + vertexID
+ "_part");
return localFs.exists(local);
} catch (IOException ioe) {
LOG.warn(StringUtils.stringifyException(ioe));
}
return false;
}
private static boolean checkForCheckpoint(final ExecutionVertexID vertexID, final String suffix) {
try {
final Path local = new Path(getLocalCheckpointPath() + Path.SEPARATOR + METADATA_PREFIX + "_" + vertexID
+ suffix);
final FileSystem localFs = local.getFileSystem();
if (localFs.exists(local)) {
return true;
}
if (!allowDistributedCheckpoints()) {
return false;
}
final Path distributedCheckpointPath = getDistributedCheckpointPath();
if (distributedCheckpointPath == null) {
return false;
}
final Path distributed = new Path(distributedCheckpointPath + Path.SEPARATOR + METADATA_PREFIX + "_"
+ vertexID
+ suffix);
final FileSystem distFs = distributed.getFileSystem();
return distFs.exists(distributed);
} catch (IOException ioe) {
LOG.warn(StringUtils.stringifyException(ioe));
}
return false;
}
/**
* Removes the checkpoint of the vertex with the given ID. All files contained in the checkpoint are deleted.
*
* @param vertexID
* the vertex whose checkpoint shall be removed
*/
public static void removeCheckpoint(final ExecutionVertexID vertexID) {
final Path localChPath = getLocalCheckpointPath();
try {
if (!removeCheckpointMetaData(new Path(localChPath + Path.SEPARATOR + METADATA_PREFIX + "_" + vertexID))) {
final Path distributedChPath = getDistributedCheckpointPath();
if (distributedChPath != null && allowDistributedCheckpoints()) {
removeCheckpointMetaData(new Path(distributedChPath + Path.SEPARATOR + METADATA_PREFIX + "_"
+ vertexID));
}
}
FileBufferManager.deleteFile(vertexID);
} catch (IOException e) {
e.printStackTrace();
}
}
private static boolean removeCheckpointMetaData(final Path pathPrefix) throws IOException {
boolean removed = false;
Path p = pathPrefix.suffix("_part");
FileSystem fs = p.getFileSystem();
if (fs.exists(p)) {
fs.delete(p, false);
removed = true;
}
int suffix = 0;
while (true) {
p = pathPrefix.suffix("_" + suffix++);
if (fs.exists(p)) {
fs.delete(p, false);
removed = true;
} else {
break;
}
}
p = pathPrefix.suffix(COMPLETED_CHECKPOINT_SUFFIX);
if (fs.exists(p)) {
fs.delete(p, false);
removed = true;
}
return removed;
}
public static CheckpointMode getCheckpointMode() {
if (CHECKPOINT_MODE == null) {
final String mode = GlobalConfiguration.getString("checkpoint.mode", "never").toLowerCase();
if ("always".equals(mode)) {
CHECKPOINT_MODE = CheckpointMode.ALWAYS;
} else if ("network".equals(mode)) {
CHECKPOINT_MODE = CheckpointMode.NETWORK;
} else {
CHECKPOINT_MODE = CheckpointMode.NEVER;
}
}
return CHECKPOINT_MODE;
}
public static boolean allowDistributedCheckpoints() {
return false;
}
}