Skip to content

Commit

Permalink
Added test util for file chunking and aggregating to output file with…
Browse files Browse the repository at this point in the history
… verification of file content
  • Loading branch information
Jai Balani committed Jan 28, 2025
1 parent 439733d commit 388fb15
Showing 1 changed file with 69 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,15 @@
import com.github.ambry.utils.Time;
import com.github.ambry.utils.Utils;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -496,6 +501,7 @@ public void startup() throws InstantiationException {
fileStore.start();

testE2EFlow();
testChunkAggregateWithStateBuildForFileCopy();
// testFileStoreUtils();
} catch (Exception e) {
logger.error("Error during startup", e);
Expand Down Expand Up @@ -551,6 +557,69 @@ private void testFileStoreUtils() throws StoreException, IOException {
System.out.println("Parsed log file contents read for offset=" + offset + ", size=" + size + " is: " + StandardCharsets.UTF_8.decode(byteBuffer));
}

private void testChunkAggregateWithStateBuildForFileCopy() throws IOException {
String chunkPath = "/tmp/0/test_chunk"; // The path to the chunk file
String logFilePath = "/tmp/0/0_log"; // The path to the log file where chunks are written
String outputFilePath = "/tmp/0/output_log_copy"; // New file where the log data will be copied

int numChunksToWrite = 10; // Number of times the chunk should be written to the log file
int chunkSize = 0;

Path path = Paths.get(logFilePath);
if (Files.exists(path)) {
// If the file exists, delete it
System.out.println("File exists. Deleting the file: " + logFilePath);
Files.delete(path); // Delete the existing file
}
System.out.println("Creating a new file: " + logFilePath);
Files.createFile(path); // Create a new file

// Step 1: Write the chunk to the logFilePath multiple times
for (int i = 0; i < numChunksToWrite; i++) {
try (FileInputStream inputStream = new FileInputStream(chunkPath)) {
chunkSize = inputStream.available();
System.out.println("Trying to put chunk to file for chunk at " + chunkPath);
// Assuming fileStore.putChunkToFile() writes data from the input stream to the log file
fileStore.putChunkToFile(logFilePath, inputStream);
System.out.println("Written chunk " + (i + 1) + " to " + logFilePath);
} catch (IOException e) {
System.err.println("An error occurred while reading or writing the chunk: " + e.getMessage());
}
}


// Step 2: Read from logFilePath chunk by chunk and write to a new file in the same directory
int offset = 0;
try (FileInputStream logInputStream = new FileInputStream(logFilePath);
FileOutputStream outputStream = new FileOutputStream(outputFilePath)) {

byte[] buffer = new byte[chunkSize];
int bytesRead;
while ((bytesRead = logInputStream.read(buffer)) != -1) {
// Write the chunk to the new file
outputStream.write(buffer, 0, bytesRead);
offset += bytesRead;

System.out.println("Writing chunk to new file at offset " + offset);
}

// Verify if contents of both files are same
byte[] content1 = Files.readAllBytes(Paths.get(logFilePath));
byte[] content2 = Files.readAllBytes(Paths.get(outputFilePath));
// Compare the byte arrays
if (Arrays.equals(content1, content2)) {
System.out.println("Input and output files are identical.");
} else {
System.out.println("Input and output files differ.");
}
System.out.println("File copy completed. Data written to " + outputFilePath);
} catch (IOException e) {
System.err.println("An error occurred while reading or writing the log file: " + e.getMessage());
}

// TODO: Run state build on the aggregated output file to see if the state is built correctly post filecopy
}

/**
* This method is expected to be called in the exit path as long as the AmbryServer instance construction was
* successful. This is expected to be called even if {@link #startup()} did not succeed.
Expand Down

0 comments on commit 388fb15

Please sign in to comment.