[HUDI-781] Add HoodieWriteableTestTable (#2040)
- Introduce HoodieWriteableTestTable for writing records into files - Migrate writeParquetFiles() in HoodieClientTestUtils to HoodieWriteableTestTable - Adopt HoodieWrittableTestTable for test cases in - ITTestRepairsCommand.java - TestHoodieIndex.java - TestHoodieKeyLocationFetchHandle.java - TestHoodieGlobalBloomIndex.java - TestHoodieBloomIndex.java - Renamed HoodieTestTable and FileCreateUtils APIs - dataFile changed to baseFile
This commit is contained in:
@@ -21,6 +21,7 @@ package org.apache.hudi.common.testutils;
|
||||
|
||||
import org.apache.hudi.common.fs.FSUtils;
|
||||
import org.apache.hudi.common.model.HoodieFileFormat;
|
||||
import org.apache.hudi.common.model.HoodiePartitionMetadata;
|
||||
import org.apache.hudi.common.model.IOType;
|
||||
import org.apache.hudi.common.table.HoodieTableMetaClient;
|
||||
import org.apache.hudi.common.table.timeline.HoodieTimeline;
|
||||
@@ -40,6 +41,32 @@ import java.util.Map;
|
||||
|
||||
public class FileCreateUtils {
|
||||
|
||||
private static final String WRITE_TOKEN = "1-0-1";
|
||||
|
||||
public static String baseFileName(String instantTime, String fileId) {
|
||||
return baseFileName(instantTime, fileId, HoodieFileFormat.PARQUET.getFileExtension());
|
||||
}
|
||||
|
||||
public static String baseFileName(String instantTime, String fileId, String fileExtension) {
|
||||
return FSUtils.makeDataFileName(instantTime, WRITE_TOKEN, fileId, fileExtension);
|
||||
}
|
||||
|
||||
public static String logFileName(String instantTime, String fileId, int version) {
|
||||
return logFileName(instantTime, fileId, version, HoodieFileFormat.HOODIE_LOG.getFileExtension());
|
||||
}
|
||||
|
||||
public static String logFileName(String instantTime, String fileId, int version, String fileExtension) {
|
||||
return FSUtils.makeLogFileName(fileId, fileExtension, instantTime, version, WRITE_TOKEN);
|
||||
}
|
||||
|
||||
public static String markerFileName(String instantTime, String fileId, IOType ioType) {
|
||||
return markerFileName(instantTime, fileId, ioType, HoodieFileFormat.PARQUET.getFileExtension());
|
||||
}
|
||||
|
||||
public static String markerFileName(String instantTime, String fileId, IOType ioType, String fileExtension) {
|
||||
return String.format("%s_%s_%s%s%s.%s", fileId, WRITE_TOKEN, instantTime, fileExtension, HoodieTableMetaClient.MARKER_EXTN, ioType);
|
||||
}
|
||||
|
||||
private static void createMetaFile(String basePath, String instantTime, String suffix) throws IOException {
|
||||
Path parentPath = Paths.get(basePath, HoodieTableMetaClient.METAFOLDER_NAME);
|
||||
Files.createDirectories(parentPath);
|
||||
@@ -73,45 +100,52 @@ public class FileCreateUtils {
|
||||
createMetaFile(basePath, instantTime, HoodieTimeline.INFLIGHT_DELTA_COMMIT_EXTENSION);
|
||||
}
|
||||
|
||||
public static void createDataFile(String basePath, String partitionPath, String instantTime, String fileId)
|
||||
throws Exception {
|
||||
createDataFile(basePath, partitionPath, instantTime, fileId, 0);
|
||||
}
|
||||
|
||||
public static void createDataFile(String basePath, String partitionPath, String instantTime, String fileId, long length)
|
||||
throws Exception {
|
||||
public static void createPartitionMetaFile(String basePath, String partitionPath) throws IOException {
|
||||
Path parentPath = Paths.get(basePath, partitionPath);
|
||||
Files.createDirectories(parentPath);
|
||||
Path dataFilePath = parentPath.resolve(FSUtils.makeDataFileName(instantTime, "1-0-1", fileId));
|
||||
if (Files.notExists(dataFilePath)) {
|
||||
Files.createFile(dataFilePath);
|
||||
Path metaFilePath = parentPath.resolve(HoodiePartitionMetadata.HOODIE_PARTITION_METAFILE);
|
||||
if (Files.notExists(metaFilePath)) {
|
||||
Files.createFile(metaFilePath);
|
||||
}
|
||||
new RandomAccessFile(dataFilePath.toFile(), "rw").setLength(length);
|
||||
}
|
||||
|
||||
public static void createLogFile(String basePath, String partitionPath, String baseInstantTime, String fileId, int version)
|
||||
public static void createBaseFile(String basePath, String partitionPath, String instantTime, String fileId)
|
||||
throws Exception {
|
||||
createLogFile(basePath, partitionPath, baseInstantTime, fileId, version, 0);
|
||||
createBaseFile(basePath, partitionPath, instantTime, fileId, 0);
|
||||
}
|
||||
|
||||
public static void createLogFile(String basePath, String partitionPath, String baseInstantTime, String fileId, int version, int length)
|
||||
public static void createBaseFile(String basePath, String partitionPath, String instantTime, String fileId, long length)
|
||||
throws Exception {
|
||||
Path parentPath = Paths.get(basePath, partitionPath);
|
||||
Files.createDirectories(parentPath);
|
||||
Path logFilePath = parentPath.resolve(FSUtils.makeLogFileName(fileId, HoodieFileFormat.HOODIE_LOG.getFileExtension(), baseInstantTime, version, "1-0-1"));
|
||||
Path baseFilePath = parentPath.resolve(baseFileName(instantTime, fileId));
|
||||
if (Files.notExists(baseFilePath)) {
|
||||
Files.createFile(baseFilePath);
|
||||
}
|
||||
new RandomAccessFile(baseFilePath.toFile(), "rw").setLength(length);
|
||||
}
|
||||
|
||||
public static void createLogFile(String basePath, String partitionPath, String instantTime, String fileId, int version)
|
||||
throws Exception {
|
||||
createLogFile(basePath, partitionPath, instantTime, fileId, version, 0);
|
||||
}
|
||||
|
||||
public static void createLogFile(String basePath, String partitionPath, String instantTime, String fileId, int version, int length)
|
||||
throws Exception {
|
||||
Path parentPath = Paths.get(basePath, partitionPath);
|
||||
Files.createDirectories(parentPath);
|
||||
Path logFilePath = parentPath.resolve(logFileName(instantTime, fileId, version));
|
||||
if (Files.notExists(logFilePath)) {
|
||||
Files.createFile(logFilePath);
|
||||
}
|
||||
new RandomAccessFile(logFilePath.toFile(), "rw").setLength(length);
|
||||
}
|
||||
|
||||
public static String createMarkerFile(String basePath, String partitionPath, String instantTime, String fileID, IOType ioType)
|
||||
public static String createMarkerFile(String basePath, String partitionPath, String instantTime, String fileId, IOType ioType)
|
||||
throws IOException {
|
||||
Path folderPath = Paths.get(basePath, HoodieTableMetaClient.TEMPFOLDER_NAME, instantTime, partitionPath);
|
||||
Files.createDirectories(folderPath);
|
||||
String markerFileName = String.format("%s_%s_%s%s%s.%s", fileID, "1-0-1", instantTime,
|
||||
HoodieFileFormat.PARQUET.getFileExtension(), HoodieTableMetaClient.MARKER_EXTN, ioType);
|
||||
Path markerFilePath = folderPath.resolve(markerFileName);
|
||||
Path parentPath = Paths.get(basePath, HoodieTableMetaClient.TEMPFOLDER_NAME, instantTime, partitionPath);
|
||||
Files.createDirectories(parentPath);
|
||||
Path markerFilePath = parentPath.resolve(markerFileName(instantTime, fileId, ioType));
|
||||
if (Files.notExists(markerFilePath)) {
|
||||
Files.createFile(markerFilePath);
|
||||
}
|
||||
@@ -119,11 +153,11 @@ public class FileCreateUtils {
|
||||
}
|
||||
|
||||
public static long getTotalMarkerFileCount(String basePath, String partitionPath, String instantTime, IOType ioType) throws IOException {
|
||||
Path markerDir = Paths.get(basePath, HoodieTableMetaClient.TEMPFOLDER_NAME, instantTime, partitionPath);
|
||||
if (Files.notExists(markerDir)) {
|
||||
Path parentPath = Paths.get(basePath, HoodieTableMetaClient.TEMPFOLDER_NAME, instantTime, partitionPath);
|
||||
if (Files.notExists(parentPath)) {
|
||||
return 0;
|
||||
}
|
||||
return Files.list(markerDir).filter(p -> p.getFileName().toString()
|
||||
return Files.list(parentPath).filter(p -> p.getFileName().toString()
|
||||
.endsWith(String.format("%s.%s", HoodieTableMetaClient.MARKER_EXTN, ioType))).count();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
package org.apache.hudi.common.testutils;
|
||||
|
||||
import org.apache.hudi.common.fs.FSUtils;
|
||||
import org.apache.hudi.common.model.HoodieFileFormat;
|
||||
import org.apache.hudi.common.model.IOType;
|
||||
import org.apache.hudi.common.table.HoodieTableMetaClient;
|
||||
import org.apache.hudi.common.util.ValidationUtils;
|
||||
@@ -39,6 +37,7 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.baseFileName;
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.createCommit;
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.createDeltaCommit;
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.createInflightCommit;
|
||||
@@ -46,15 +45,16 @@ import static org.apache.hudi.common.testutils.FileCreateUtils.createInflightDel
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.createMarkerFile;
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.createRequestedCommit;
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.createRequestedDeltaCommit;
|
||||
import static org.apache.hudi.common.testutils.FileCreateUtils.logFileName;
|
||||
|
||||
public class HoodieTestTable {
|
||||
|
||||
private final String basePath;
|
||||
private final FileSystem fs;
|
||||
private HoodieTableMetaClient metaClient;
|
||||
private String currentInstantTime;
|
||||
protected final String basePath;
|
||||
protected final FileSystem fs;
|
||||
protected HoodieTableMetaClient metaClient;
|
||||
protected String currentInstantTime;
|
||||
|
||||
private HoodieTestTable(String basePath, FileSystem fs, HoodieTableMetaClient metaClient) {
|
||||
protected HoodieTestTable(String basePath, FileSystem fs, HoodieTableMetaClient metaClient) {
|
||||
ValidationUtils.checkArgument(Objects.equals(basePath, metaClient.getBasePath()));
|
||||
ValidationUtils.checkArgument(Objects.equals(fs, metaClient.getRawFs()));
|
||||
this.basePath = basePath;
|
||||
@@ -124,6 +124,13 @@ public class HoodieTestTable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public HoodieTestTable withPartitionMetaFiles(String... partitionPaths) throws IOException {
|
||||
for (String partitionPath : partitionPaths) {
|
||||
FileCreateUtils.createPartitionMetaFile(basePath, partitionPath);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public HoodieTestTable withMarkerFile(String partitionPath, IOType ioType) throws IOException {
|
||||
return withMarkerFile(partitionPath, UUID.randomUUID().toString(), ioType);
|
||||
}
|
||||
@@ -150,19 +157,19 @@ public class HoodieTestTable {
|
||||
*
|
||||
* @return A {@link Map} of partition and its newly inserted file's id.
|
||||
*/
|
||||
public Map<String, String> withInserts(String... partitions) throws Exception {
|
||||
public Map<String, String> withBaseFilesInPartitions(String... partitions) throws Exception {
|
||||
Map<String, String> partitionFileIdMap = new HashMap<>();
|
||||
for (String p : partitions) {
|
||||
String fileId = UUID.randomUUID().toString();
|
||||
FileCreateUtils.createDataFile(basePath, p, currentInstantTime, fileId);
|
||||
FileCreateUtils.createBaseFile(basePath, p, currentInstantTime, fileId);
|
||||
partitionFileIdMap.put(p, fileId);
|
||||
}
|
||||
return partitionFileIdMap;
|
||||
}
|
||||
|
||||
public HoodieTestTable withUpdates(String partition, String... fileIds) throws Exception {
|
||||
public HoodieTestTable withBaseFilesInPartition(String partition, String... fileIds) throws Exception {
|
||||
for (String f : fileIds) {
|
||||
FileCreateUtils.createDataFile(basePath, partition, currentInstantTime, f);
|
||||
FileCreateUtils.createBaseFile(basePath, partition, currentInstantTime, f);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -182,35 +189,37 @@ public class HoodieTestTable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean filesExist(Map<String, String> partitionAndFileId, String instantTime) {
|
||||
public boolean baseFilesExist(Map<String, String> partitionAndFileId, String instantTime) {
|
||||
return partitionAndFileId.entrySet().stream().allMatch(entry -> {
|
||||
String partition = entry.getKey();
|
||||
String fileId = entry.getValue();
|
||||
return fileExists(partition, instantTime, fileId);
|
||||
return baseFileExists(partition, instantTime, fileId);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean filesExist(String partition, String instantTime, String... fileIds) {
|
||||
return Arrays.stream(fileIds).allMatch(f -> fileExists(partition, instantTime, f));
|
||||
public boolean baseFilesExist(String partition, String instantTime, String... fileIds) {
|
||||
return Arrays.stream(fileIds).allMatch(f -> baseFileExists(partition, instantTime, f));
|
||||
}
|
||||
|
||||
public boolean fileExists(String partition, String instantTime, String fileId) {
|
||||
public boolean baseFileExists(String partition, String instantTime, String fileId) {
|
||||
try {
|
||||
return fs.exists(new Path(Paths.get(basePath, partition,
|
||||
FSUtils.makeDataFileName(instantTime, "1-0-1", fileId)).toString()));
|
||||
return fs.exists(new Path(Paths.get(basePath, partition, baseFileName(instantTime, fileId)).toString()));
|
||||
} catch (IOException e) {
|
||||
throw new HoodieTestTableException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getBaseFileNameById(String fileId) {
|
||||
return baseFileName(currentInstantTime, fileId);
|
||||
}
|
||||
|
||||
public boolean logFilesExist(String partition, String instantTime, String fileId, int... versions) {
|
||||
return Arrays.stream(versions).allMatch(v -> logFileExists(partition, instantTime, fileId, v));
|
||||
}
|
||||
|
||||
public boolean logFileExists(String partition, String instantTime, String fileId, int version) {
|
||||
try {
|
||||
return fs.exists(new Path(Paths.get(basePath, partition,
|
||||
FSUtils.makeLogFileName(fileId, HoodieFileFormat.HOODIE_LOG.getFileExtension(), instantTime, version, "1-0-1")).toString()));
|
||||
return fs.exists(new Path(Paths.get(basePath, partition, logFileName(instantTime, fileId, version)).toString()));
|
||||
} catch (IOException e) {
|
||||
throw new HoodieTestTableException(e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user