blob: 334f58e32f04880423069b2fe149147d79e9a31d [file] [log] [blame]
package org.apache.cassandra.sidecar.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import javax.validation.constraints.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Builds file path after verifying it exists
*/
public abstract class FilePathBuilder
{
private static final Logger logger = LoggerFactory.getLogger(FilePathBuilder.class);
private static final String dataSubDir = "/data";
private final Collection<String> dataDirs;
public FilePathBuilder(@NotNull final Collection<String> dataDirs)
{
this.dataDirs = dataDirs;
}
public abstract Path build(String keyspace, String table, String snapshot, String component)
throws FileNotFoundException;
String addKeyspaceToPath(String keyspace) throws FileNotFoundException
{
for (String dir : dataDirs)
{
StringBuilder path = new StringBuilder(dir);
if (addFileToPathIfPresent(path, keyspace, true))
{
return path.toString();
}
if (dir.endsWith(dataSubDir))
{
continue;
}
// check in "data" sub directory
if (addFileToPathIfPresent(path.append(dataSubDir), keyspace, true))
{
return path.toString();
}
}
throw new FileNotFoundException("Keyspace " + keyspace + " does not exist");
}
String addTableToPath(String table, String path) throws FileNotFoundException
{
final StringBuilder modifiedPath = new StringBuilder(path);
if (addFileToPathIfPresent(modifiedPath, table, false))
{
return modifiedPath.toString();
}
throw new FileNotFoundException("Table " + table + " not found, path searched: " + path);
}
String addSnapshotToPath(String snapshot, String path) throws FileNotFoundException
{
final StringBuilder modifiedPath = new StringBuilder(path);
if (addFileToPathIfPresent(modifiedPath.append("/snapshots"), snapshot, true))
{
return modifiedPath.toString();
}
throw new FileNotFoundException("Snapshot " + snapshot + " not found, path searched: " + path);
}
String addSSTableComponentToPath(String component, String path) throws FileNotFoundException
{
final StringBuilder modifiedPath = new StringBuilder(path);
if (addFileToPathIfPresent(modifiedPath, component, true))
{
return modifiedPath.toString();
}
throw new FileNotFoundException("Component " + component + " not found, path searched: " + path);
}
private boolean addFileToPathIfPresent(StringBuilder path, String file, boolean checkEqual)
throws FileNotFoundException
{
final Path fileDir = Paths.get(path.toString());
if (!checkDirExists(fileDir))
{
throw new FileNotFoundException(fileDir + " directory empty or does not exist!");
}
try
{
Path finalPath = null;
try (final DirectoryStream<Path> dirEntries = Files.newDirectoryStream(fileDir))
{
for (Path entry : dirEntries)
{
final Path filePath = entry.getFileName();
if (filePath == null)
{
continue;
}
final String fileName = filePath.toString();
if (fileName.equals(file) || (!checkEqual && fileName.startsWith(file + "-")))
{
if (finalPath == null
|| Files.getLastModifiedTime(entry).compareTo(Files.getLastModifiedTime(finalPath)) > 0)
{
finalPath = entry;
}
}
}
if (finalPath != null)
{
final Path finalFilePath = finalPath.getFileName();
if (finalFilePath == null)
{
return false;
}
final String finalFileName = finalFilePath.toString();
path.append('/').append(finalFileName);
return true;
}
}
}
catch (IOException e)
{
logger.error("Error listing files in path {}, could not add file {} to path", path, file, e);
throw new RuntimeException("Failed to list files in path " + path);
}
return false;
}
private boolean checkDirExists(final Path path)
{
final File file = new File(path.toString());
return file.exists() && file.isDirectory();
}
}