-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FFDB-007: add PersistableFileTable implementation (#14)
- Loading branch information
Showing
8 changed files
with
240 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
src/main/java/com/sahilbondre/firefly/filetable/FilePointer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.sahilbondre.firefly.filetable; | ||
|
||
import java.util.Objects; | ||
|
||
public class FilePointer { | ||
private String fileName; | ||
private long offset; | ||
|
||
public FilePointer(String fileName, long offset) { | ||
this.fileName = fileName; | ||
this.offset = offset; | ||
} | ||
|
||
public FilePointer() { | ||
} | ||
|
||
public String getFileName() { | ||
return fileName; | ||
} | ||
|
||
public void setFileName(String fileName) { | ||
this.fileName = fileName; | ||
} | ||
|
||
public long getOffset() { | ||
return offset; | ||
} | ||
|
||
public void setOffset(long offset) { | ||
this.offset = offset; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
FilePointer that = (FilePointer) o; | ||
return offset == that.offset && fileName.equals(that.fileName); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(fileName, offset); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/sahilbondre/firefly/filetable/InvalidFileTableException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.sahilbondre.firefly.filetable; | ||
|
||
public class InvalidFileTableException extends RuntimeException { | ||
public InvalidFileTableException(String message) { | ||
super(message); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/com/sahilbondre/firefly/filetable/PersistableFileTable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.sahilbondre.firefly.filetable; | ||
|
||
import java.io.FileNotFoundException; | ||
|
||
public interface PersistableFileTable { | ||
void put(byte[] key, FilePointer value); | ||
|
||
FilePointer get(byte[] key); | ||
|
||
void saveToDisk(String filePath) throws FileNotFoundException; | ||
} |
58 changes: 58 additions & 0 deletions
58
src/main/java/com/sahilbondre/firefly/filetable/SerializedPersistableFileTable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package com.sahilbondre.firefly.filetable; | ||
|
||
import com.esotericsoftware.kryo.Kryo; | ||
import com.esotericsoftware.kryo.KryoException; | ||
import com.esotericsoftware.kryo.io.Input; | ||
import com.esotericsoftware.kryo.io.Output; | ||
|
||
import java.io.*; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class SerializedPersistableFileTable implements PersistableFileTable, Serializable { | ||
|
||
private static final Kryo kryo = new Kryo(); | ||
|
||
private final Map<String, FilePointer> table; | ||
|
||
public SerializedPersistableFileTable() { | ||
kryo.register(SerializedPersistableFileTable.class); | ||
kryo.register(HashMap.class); | ||
kryo.register(FilePointer.class); | ||
this.table = new HashMap<>(); | ||
} | ||
|
||
public static SerializedPersistableFileTable fromEmpty() { | ||
return new SerializedPersistableFileTable(); | ||
} | ||
|
||
public static SerializedPersistableFileTable fromFile(String filePath) throws FileNotFoundException, KryoException { | ||
try (Input input = new Input(new FileInputStream(filePath))) { | ||
return kryo.readObject(input, SerializedPersistableFileTable.class); | ||
} catch (KryoException e) { | ||
throw new InvalidFileTableException("Failed to load FileTable from disk: " + e.getMessage()); | ||
} | ||
} | ||
|
||
@Override | ||
public void put(byte[] key, FilePointer value) { | ||
if (key != null && value != null) { | ||
table.put(new String(key), value); | ||
} | ||
} | ||
|
||
@Override | ||
public FilePointer get(byte[] key) { | ||
if (key != null) { | ||
return table.get(new String(key)); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public void saveToDisk(String filePath) throws FileNotFoundException { | ||
Output output = new Output(new FileOutputStream(filePath)); | ||
kryo.writeObject(output, this); | ||
output.close(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
src/main/java/com/sahilbondre/firefly/log/RandomAccessLog.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
src/test/java/com/sahilbondre/firefly/filetable/SerializedPersistableFileTableTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package com.sahilbondre.firefly.filetable; | ||
|
||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.List; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
class SerializedPersistableFileTableTest { | ||
|
||
private static final String TEST_FILE_PATH = "src/test/resources/map"; | ||
private SerializedPersistableFileTable fileTable; | ||
|
||
@BeforeEach | ||
void setUp() throws IOException { | ||
Files.deleteIfExists(Paths.get(TEST_FILE_PATH)); | ||
fileTable = SerializedPersistableFileTable.fromEmpty(); | ||
} | ||
|
||
@AfterEach | ||
void tearDown() throws IOException { | ||
Files.deleteIfExists(Paths.get(TEST_FILE_PATH)); | ||
} | ||
|
||
@Test | ||
void given_KeyValue_When_PuttingAndGet_Then_RetrievedValueMatches() { | ||
// Given | ||
byte[] key = "testKey".getBytes(); | ||
FilePointer expectedValue = new FilePointer("test.txt", 42); | ||
|
||
// When | ||
fileTable.put(key, new FilePointer("test.txt", 42)); | ||
FilePointer retrievedValue = fileTable.get(key); | ||
|
||
// Then | ||
assertEquals(expectedValue, retrievedValue); | ||
} | ||
|
||
@Test | ||
void given_NullKey_When_PuttingAndGet_Then_RetrievedValueIsNull() { | ||
// Given | ||
FilePointer value = new FilePointer("test.txt", 42); | ||
|
||
// When | ||
fileTable.put(null, value); | ||
FilePointer retrievedValue = fileTable.get(null); | ||
|
||
// Then | ||
assertNull(retrievedValue); | ||
} | ||
|
||
@Test | ||
void given_NullValue_When_PuttingAndGet_Then_RetrievedValueIsNull() { | ||
// Given | ||
byte[] key = "testKey".getBytes(); | ||
|
||
// When | ||
fileTable.put(key, null); | ||
FilePointer retrievedValue = fileTable.get(key); | ||
|
||
// Then | ||
assertNull(retrievedValue); | ||
} | ||
|
||
@Test | ||
void given_KeyValue_When_SavingToDiskAndLoadingFromFile_Then_RetrievedValueMatches() throws FileNotFoundException { | ||
// Given | ||
byte[] key = "testKey".getBytes(); | ||
FilePointer value = new FilePointer("test.txt", 42); | ||
|
||
// When | ||
fileTable.put(key, value); | ||
fileTable.saveToDisk(TEST_FILE_PATH); | ||
SerializedPersistableFileTable loadedFileTable = SerializedPersistableFileTable.fromFile(TEST_FILE_PATH); | ||
FilePointer retrievedValue = loadedFileTable.get(key); | ||
|
||
// Then | ||
assertEquals(value, retrievedValue); | ||
} | ||
|
||
@Test | ||
void given_NonexistentFile_When_LoadingFromFile_Then_FileNotFoundExceptionIsThrown() { | ||
// When | ||
// Then | ||
assertThrows(FileNotFoundException.class, | ||
() -> SerializedPersistableFileTable.fromFile(TEST_FILE_PATH)); | ||
} | ||
|
||
@Test | ||
void given_CorruptedFile_When_LoadingFromFile_Then_InvalidFileTableExceptionIsThrown() throws IOException { | ||
// Given | ||
// Create a corrupted file by writing invalid data | ||
Path filePath = Paths.get(TEST_FILE_PATH); | ||
Files.write(filePath, List.of("Invalid Data")); | ||
|
||
// Then | ||
assertThrows(InvalidFileTableException.class, | ||
() -> SerializedPersistableFileTable.fromFile(TEST_FILE_PATH)); | ||
} | ||
} |