blob: bc2f5bc35ca84df9665eaa09da3867f2b585c1d3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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 org.apache.geode.internal.cache.backup;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.internal.cache.DiskStoreImpl;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.util.TransformUtils;
class FileSystemIncrementalBackupLocation implements IncrementalBackupLocation {
private static final String INCOMPLETE_BACKUP_FILE = "INCOMPLETE_BACKUP_FILE";
private final Path memberBackupLocationDir;
FileSystemIncrementalBackupLocation(File backupLocationDir, String memberId) {
memberBackupLocationDir = new File(backupLocationDir, memberId).toPath();
}
Path getMemberBackupLocationDir() {
return memberBackupLocationDir;
}
@Override
public Map<String, File> getBackedUpOplogs(DiskStore diskStore) throws IOException {
File checkedBaselineDir = checkBaseline(diskStore);
if (checkedBaselineDir == null) {
return Collections.emptyMap();
}
Collection<File> baselineOplogFiles = getBackedUpOplogs(checkedBaselineDir, diskStore);
baselineOplogFiles.addAll(getPreviouslyBackedUpOpLogs(checkedBaselineDir));
// Map of baseline oplog file name to oplog file
return TransformUtils.transformAndMap(baselineOplogFiles, TransformUtils.fileNameTransformer);
}
Collection<File> getBackedUpOplogs(File checkedBaselineDir, DiskStore diskStore) {
File baselineDir = new File(checkedBaselineDir, BackupWriter.DATA_STORES_DIRECTORY);
baselineDir = new File(baselineDir, getBackupDirName((DiskStoreImpl) diskStore));
return FileUtils.listFiles(baselineDir, new String[] {"krf", "drf", "crf"}, true);
}
Collection<File> getPreviouslyBackedUpOpLogs(File checkedBaselineDir) throws IOException {
BackupInspector inspector = createBackupInspector(checkedBaselineDir);
HashSet<File> oplogs = new HashSet<>();
if (inspector.isIncremental() && inspector.getIncrementalOplogFileNames() != null) {
inspector.getIncrementalOplogFileNames().forEach(oplog -> {
oplog = inspector.getCopyFromForOplogFile(oplog);
oplogs.add(new File(oplog));
});
}
return oplogs;
}
BackupInspector createBackupInspector(File checkedBaselineDir) throws IOException {
return BackupInspector.createInspector(checkedBaselineDir);
}
/**
* Performs a sanity check on the baseline directory for incremental backups. If a baseline
* directory exists for the member and there is no INCOMPLETE_BACKUP_FILE file then return the
* data stores directory for this member.
*/
private File checkBaseline(DiskStore diskStore) {
File baselineDir = memberBackupLocationDir.toFile();
if (!baselineDir.exists()) {
// hmmm, did this member have a restart? Determine which member dir might be a match for us
baselineDir = findBaselineForThisMember(memberBackupLocationDir.getParent(), diskStore);
}
if (null != baselineDir) {
// check for existence of INCOMPLETE_BACKUP_FILE file
File incompleteBackup = new File(baselineDir, INCOMPLETE_BACKUP_FILE);
if (incompleteBackup.exists()) {
baselineDir = null;
}
}
return baselineDir;
}
private File findBaselineForThisMember(Path baselineParentDir, DiskStore diskStore) {
File baselineDir = null;
// Find the first matching DiskStoreId directory for this member.
File[] matchingFiles = baselineParentDir.toFile()
.listFiles((file, name) -> name.endsWith(getBackupDirName((DiskStoreImpl) diskStore)));
// We found it? Good. Set this member's baseline to the backed up disk store's member dir (two
// levels up).
if (null != matchingFiles && matchingFiles.length > 0) {
baselineDir = matchingFiles[0].getParentFile().getParentFile();
}
return baselineDir;
}
/**
* Returns the dir name used to back up this DiskStore's directories under. The name is a
* concatenation of the disk store name and id.
*/
String getBackupDirName(DiskStoreImpl diskStore) {
String name = diskStore.getName();
if (name == null) {
name = GemFireCacheImpl.getDefaultDiskStoreName();
}
return name + "_" + diskStore.getDiskStoreID().toString();
}
}