com.gemstone.gemfire.internal.cache.persistence.RestoreScript 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
The newest version!
/*
* 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.cache.persistence;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.gemstone.gemfire.internal.FileUtil;
import com.gemstone.gemfire.internal.concurrent.CFactory;
/**
* This class is used to automatically generate a restore script for a backup.
* It keeps a list of files that were backed up, and a list of files that
* we should test for to avoid overriding when we restore the backup.
*
* It generates either a restore.sh for unix or a restore.bat for windows.
*
* @author dsmith
*
*/
public class RestoreScript {
public static final String EXIT_MARKER = "Exit Functions";
private static final ScriptGenerator UNIX_GENERATOR = new UnixScriptGenerator();
private static final ScriptGenerator WINDOWS_GENERATOR = new WindowsScriptGenerator();
private Map baselineFiles = new LinkedHashMap();
private final Map backedUpFiles = new LinkedHashMap();
private final List existenceTests = new ArrayList();
public void addBaselineFiles(Map baselineFiles) {
this.baselineFiles.putAll(baselineFiles);
}
public void addFile(File originalFile, File backupFile) {
backedUpFiles.put(backupFile, originalFile.getAbsoluteFile());
}
public void addExistenceTest(File originalFile) {
existenceTests.add(originalFile.getAbsoluteFile());
}
public void generate(File outputDir) throws FileNotFoundException {
if(isWindows()) {
generateWindowsScript(outputDir);
} else {
generateUnixScript(outputDir);
}
}
private void generateWindowsScript(File outputDir) throws FileNotFoundException {
File outputFile = new File(outputDir, "restore.bat");
generateScript(outputDir, outputFile, WINDOWS_GENERATOR);
}
private void generateUnixScript(File outputDir) throws FileNotFoundException {
File outputFile = new File(outputDir, "restore.sh");
generateScript(outputDir, outputFile, UNIX_GENERATOR);
}
private void generateScript(File outputDir, File outputFile, ScriptGenerator osGenerator) throws FileNotFoundException {
PrintWriter writer = new PrintWriter(outputFile);
try {
osGenerator.writePreamble(writer);
writer.println();
osGenerator.writeComment(writer, "Restore a backup of gemfire persistent data to the location it was backed up");
osGenerator.writeComment(writer, "from.");
osGenerator.writeComment(writer, "This script will refuse to restore if the original data still exists.");
writer.println();
osGenerator.writeComment(writer, "This script was automatically generated by the gemfire backup utility.");
writer.println();
osGenerator.writeComment(writer, "Test for existing originals. If they exist, do not restore the backup.");
for(File file: existenceTests) {
osGenerator.writeExistenceTest(writer, file);
}
writer.println();
osGenerator.writeComment(writer, "Restore data");
for(Map.Entry entry : backedUpFiles.entrySet()) {
File backup = entry.getKey();
boolean backupHasFiles = backup.isDirectory() && backup.list().length != 0;
backup = FileUtil.removeParent(outputDir, backup);
File original = entry.getValue();
if(original.isDirectory()) {
osGenerator.writeCopyDirectoryContents(writer, backup, original, backupHasFiles);
} else {
osGenerator.writeCopyFile(writer, backup, original);
}
}
// Write out baseline file copies in restore script (if there are any) if this is a restore for an incremental backup
if(!this.baselineFiles.isEmpty()) {
writer.println();
osGenerator.writeComment(writer, "Incremental backup. Restore baseline originals from previous backups.");
for(Map.Entry entry : this.baselineFiles.entrySet()) {
osGenerator.writeCopyFile(writer, entry.getKey(), entry.getValue());
}
}
if(isWindows()) {
osGenerator.writeExit(writer);
}
} finally {
writer.close();
}
CFactory.setExecutable(outputFile, true, true);
}
//TODO prpersist - We've got this code replicated
//in 10 different places in our product. Maybe we
//need to put this method somewhere :)
private boolean isWindows() {
String os = System.getProperty("os.name");
if (os != null) {
if (os.indexOf("Windows") != -1) {
return true;
}
}
return false;
}
private static interface ScriptGenerator
{
void writePreamble(PrintWriter writer);
void writeExit(PrintWriter writer);
void writeCopyFile(PrintWriter writer, File backup, File original);
void writeCopyDirectoryContents(PrintWriter writer, File backup, File original, boolean backupHasFiles);
void writeExistenceTest(PrintWriter writer, File file);
void writeComment(PrintWriter writer, String string);
};
private static class WindowsScriptGenerator implements ScriptGenerator {
final String ERROR_CHECK = "IF %ERRORLEVEL% GEQ 4 GOTO Exit_Bad";
public void writePreamble(PrintWriter writer) {
writer.println("echo off");
}
public void writeComment(PrintWriter writer, String string) {
writer.println("rem " + string);
}
public void writeCopyDirectoryContents(PrintWriter writer, File backup, File original, boolean backupHasFiles) {
writer.println("mkdir \"" + original + "\"");
writer.println("C:\\Windows\\System32\\Robocopy.exe \"" + backup + "\" \"" + original + "\" /e /njh /njs");
writer.println(ERROR_CHECK);
}
public void writeCopyFile(PrintWriter writer, File source, File destination) {
String fileName = source.getName();
String sourcePath = source.getParent() == null ? "." : source.getParent();
String destinationPath = destination.getParent() == null ? "." : destination.getParent();
writer.println("C:\\Windows\\System32\\Robocopy.exe \"" + sourcePath + "\" \"" + destinationPath + "\" " + fileName + " /njh /njs");
writer.println(ERROR_CHECK);
}
public void writeExistenceTest(PrintWriter writer, File file) {
writer.println("IF EXIST \"" + file + "\" echo \"Backup not restored. Refusing to overwrite " + file + "\" && exit /B 1 ");
}
public void writeExit(PrintWriter writer) {
writeComment(writer, EXIT_MARKER);
writer.println(":Exit_Good\nexit /B 0\n\n:Exit_Bad\nexit /B 1");
}
}
private static class UnixScriptGenerator implements ScriptGenerator {
public void writePreamble(PrintWriter writer) {
writer.println("#!/bin/bash -e");
writer.println("cd `dirname $0`");
}
public void writeComment(PrintWriter writer, String string) {
writer.println("#" + string);
}
public void writeCopyDirectoryContents(PrintWriter writer, File backup,
File original, boolean backupHasFiles) {
writer.println("mkdir -p '" + original + "'");
if(backupHasFiles) {
writer.println("cp -rp '" + backup + "'/* '" + original + "'");
}
}
public void writeCopyFile(PrintWriter writer, File backup, File original) {
writer.println("cp -p '" + backup + "' '" + original + "'");
}
public void writeExistenceTest(PrintWriter writer, File file) {
writer.println("test -e '" + file + "' && echo 'Backup not restored. Refusing to overwrite " + file + "' && exit 1 ");
}
public void writeExit(PrintWriter writer) {
}
}
}