Skip to content

Commit

Permalink
Refactor 'tagObject' to handle scenarios where exceptions are unneces…
Browse files Browse the repository at this point in the history
…sary and add new junit tests
  • Loading branch information
doulikecookiedough committed Feb 8, 2024
1 parent 90b4d5a commit f3e4fea
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -660,15 +660,55 @@ public void tagObject(String pid, String cid) throws IOException, PidRefsFileExi
try {
Path absPidRefsPath = getExpectedPath(pid, "refs", HashStoreIdTypes.pid.getName());
Path absCidRefsPath = getExpectedPath(cid, "refs", HashStoreIdTypes.cid.getName());
boolean pidRefsFound = Files.exists(absPidRefsPath);
boolean cidRefsFound = Files.exists(absCidRefsPath);

// Check that pid refs file doesn't exist yet
if (Files.exists(absPidRefsPath)) {
String errMsg = "FileHashStore.tagObject - pid refs file already exists for pid: "
+ pid + ". A pid can only reference one cid.";
logFileHashStore.error(errMsg);
throw new PidRefsFileExistsException(errMsg);

} else if (Files.exists(absCidRefsPath)) {
// Both files found, confirm that reference files are where they are expected to be
if (pidRefsFound && cidRefsFound) {
verifyHashStoreRefsFiles(pid, cid, absPidRefsPath, absCidRefsPath);
logFileHashStore.info(
"FileHashStore.tagObject - Object with cid: " + cid
+ " already exists and is tagged with pid: " + pid
);
} else if (pidRefsFound && !cidRefsFound) {
// If pid refs exists, it can only contain and reference one cid
// First, compare the cid retrieved from the pid refs file from the supplid cid
String retrievedCid = new String(Files.readAllBytes(absPidRefsPath));
if (retrievedCid.equalsIgnoreCase(cid)) {
// The pid correctly references the cid, but the cid refs file is missing
File cidRefsTmpFile = writeRefsFile(pid, HashStoreIdTypes.cid.getName());
File absPathCidRefsFile = absCidRefsPath.toFile();
move(cidRefsTmpFile, absPathCidRefsFile, "refs");
// Verify tagging process, this throws exceptions if there's an issue
verifyHashStoreRefsFiles(pid, cid, absPidRefsPath, absCidRefsPath);
logFileHashStore.info(
"FileHashStore.tagObject - Pid refs file exists for pid: " + pid
+ ", but cid refs file for: " + cid
+ " is missing. Missing cid refs file created and tagging completed."
);
return;
} else {
// Check if the retrieved cid refs file exists and pid is referenced
Path retrievedAbsCidRefsPath = getExpectedPath(
retrievedCid, "refs", HashStoreIdTypes.cid.getName()
);
boolean retrievedAbsCidRefsPathExists = Files.exists(retrievedAbsCidRefsPath);
if (retrievedAbsCidRefsPathExists && isStringInRefsFile(
pid, retrievedAbsCidRefsPath
)) {
// This pid is accounted for and tagged as expected.
String errMsg =
"FileHashStore.tagObject - pid refs file already exists for pid: " + pid
+ ", and the associated cid refs file contains the pid."
+ " A pid can only reference one cid.";
logFileHashStore.error(errMsg);
throw new PidRefsFileExistsException(errMsg);
}
// Orphaned pid refs file found, the retrieved cid refs file exists
// but doesn't contain the cid. Proceed to overwrite the pid refs file.
// There is no return statement, so we move out of this if block.
}
} else if (!pidRefsFound && cidRefsFound) {
// Only update cid refs file if pid is not in the file
boolean pidFoundInCidRefFiles = isStringInRefsFile(pid, absCidRefsPath);
if (!pidFoundInCidRefFiles) {
Expand All @@ -680,30 +720,28 @@ public void tagObject(String pid, String cid) throws IOException, PidRefsFileExi
move(pidRefsTmpFile, absPathPidRefsFile, "refs");
// Verify tagging process, this throws exceptions if there's an issue
verifyHashStoreRefsFiles(pid, cid, absPidRefsPath, absCidRefsPath);

logFileHashStore.info(
"FileHashStore.tagObject - Object with cid: " + cid
+ " has been updated and tagged successfully with pid: " + pid
);

} else {
// Get pid and cid refs files
File pidRefsTmpFile = writeRefsFile(cid, HashStoreIdTypes.pid.getName());
File cidRefsTmpFile = writeRefsFile(pid, HashStoreIdTypes.cid.getName());
// Move refs files to permanent location
File absPathPidRefsFile = absPidRefsPath.toFile();
File absPathCidRefsFile = absCidRefsPath.toFile();
move(pidRefsTmpFile, absPathPidRefsFile, "refs");
move(cidRefsTmpFile, absPathCidRefsFile, "refs");
// Verify tagging process, this throws exceptions if there's an issue
verifyHashStoreRefsFiles(pid, cid, absPidRefsPath, absCidRefsPath);

logFileHashStore.info(
"FileHashStore.tagObject - Object with cid: " + cid
+ " has been tagged successfully with pid: " + pid
);
return;
}

// Get pid and cid refs files
File pidRefsTmpFile = writeRefsFile(cid, HashStoreIdTypes.pid.getName());
File cidRefsTmpFile = writeRefsFile(pid, HashStoreIdTypes.cid.getName());
// Move refs files to permanent location
File absPathPidRefsFile = absPidRefsPath.toFile();
File absPathCidRefsFile = absCidRefsPath.toFile();
move(pidRefsTmpFile, absPathPidRefsFile, "refs");
move(cidRefsTmpFile, absPathCidRefsFile, "refs");
// Verify tagging process, this throws exceptions if there's an issue
verifyHashStoreRefsFiles(pid, cid, absPidRefsPath, absCidRefsPath);
logFileHashStore.info(
"FileHashStore.tagObject - Object with cid: " + cid
+ " has been tagged successfully with pid: " + pid
);

} finally {
// Release lock
synchronized (referenceLockedCids) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Properties;

import org.dataone.hashstore.ObjectMetadata;
import org.dataone.hashstore.exceptions.PidRefsFileExistsException;
import org.dataone.hashstore.filehashstore.FileHashStore.HashStoreIdTypes;
import org.dataone.hashstore.testdata.TestDataHarness;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -67,95 +69,180 @@ public void initializeFileHashStore() {
@TempDir
public Path tempFolder;


/**
* Check that tagObject creates reference files
*/
@Test
public void tagObject() throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";
fileHashStore.tagObject(pid, cid);

Path storePath = Paths.get(fhsProperties.getProperty("storePath"));
File[] pidRefsFiles = storePath.resolve("refs/pid").toFile().listFiles();
assertEquals(1, pidRefsFiles.length);
File[] cidRefsFiles = storePath.resolve("refs/cid").toFile().listFiles();
assertEquals(1, cidRefsFiles.length);
}

/**
* Check that tagObject writes expected pid refs files
*/
@Test
public void tagObject_pidRefsFile() throws Exception {
public void tagObject_pidRefsFileContent() throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";
fileHashStore.tagObject(pid, cid);

Path pidRefsFilePath = fileHashStore.getExpectedPath(pid, "refs", "pid");
assertTrue(Files.exists(pidRefsFilePath));

String retrievedCid = new String(Files.readAllBytes(pidRefsFilePath));
assertEquals(cid, retrievedCid);
}

/**
* Check that tagObject writes expected cid refs files
*/
@Test
public void tagObject_cidRefsFile() throws Exception {
public void tagObject_cidRefsFileContent() throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";
fileHashStore.tagObject(pid, cid);

Path cidRefsFilePath = fileHashStore.getExpectedPath(cid, "refs", "cid");
assertTrue(Files.exists(cidRefsFilePath));

String retrievedPid = new String(Files.readAllBytes(cidRefsFilePath));
assertEquals(pid, retrievedPid);
}

/**
* Check that tagObject throws exception when pid refs file already exists
* Check that tagObject does not throw exception when pid and cid refs
* file already exists
*/
@Test
public void tagObject_pidRefsFileExists() throws Exception {
public void tagObject_refsFileAlreadyExists() throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";
fileHashStore.tagObject(pid, cid);

assertThrows(PidRefsFileExistsException.class, () -> {
fileHashStore.tagObject(pid, cid);
});

// Should not throw any exceptions, everything is where it's supposed to be.
fileHashStore.tagObject(pid, cid);
// Confirm that there is only 1 of each refs file
Path storePath = Paths.get(fhsProperties.getProperty("storePath"));
File[] pidRefsFiles = storePath.resolve("refs/pid").toFile().listFiles();
assertEquals(1, pidRefsFiles.length);
File[] cidRefsFiles = storePath.resolve("refs/cid").toFile().listFiles();
assertEquals(1, cidRefsFiles.length);
}

/**
* Check that tagObject creates a pid refs file and updates an existing cid refs file
* Check tagObject throws exception when the supplied cid is different from what is
* found in the pid refs file, and the associated cid refs file from the pid refs file
* is correctly tagged (everything is where it's expected to be)
*/
@Test
public void tagObject_cidRefsFileExists() throws Exception {
public void tagObject_pidRefsFileFound_differentCidRetrieved_cidRefsFileFound()
throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";
fileHashStore.tagObject(pid, cid);
String existingCid = "987654321fedcba";
fileHashStore.tagObject(pid, existingCid);

String pidAdditional = "another.pid.2";
fileHashStore.tagObject(pidAdditional, cid);
// This will throw an exception because the pid and cid refs file are in sync
assertThrows(PidRefsFileExistsException.class, () -> {
fileHashStore.tagObject(pid, cid);
});
}

Path pidRefsFilePath = fileHashStore.getExpectedPath(pid, "refs", "pid");
assertTrue(Files.exists(pidRefsFilePath));

/**
* Check tagObject overwrites a oprhaned pid refs file.
*/
@Test
public void tagObject_pidRefsFileFound_differentCidRetrieved_cidRefsFileNotFound()
throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";
String cidForOrphanPidRef = "987654321fedcba";

// Check cid refs file
Path cidRefsFilePath = fileHashStore.getExpectedPath(cid, "refs", "cid");
boolean pidFoundInCidRefFiles = fileHashStore.isStringInRefsFile(
pidAdditional, cidRefsFilePath
// Create orphaned pid refs file
Path absPidRefsPath = fileHashStore.getExpectedPath(
pid, "refs", HashStoreIdTypes.pid.getName()
);
assertTrue(pidFoundInCidRefFiles);
File pidRefsTmpFile = fileHashStore.writeRefsFile(
cidForOrphanPidRef, HashStoreIdTypes.pid.getName()
);
File absPathPidRefsFile = absPidRefsPath.toFile();
fileHashStore.move(pidRefsTmpFile, absPathPidRefsFile, "refs");

fileHashStore.tagObject(pid, cid);
// There should only be 1 of each refs file
Path storePath = Paths.get(fhsProperties.getProperty("storePath"));
File[] pidRefsFiles = storePath.resolve("refs/pid").toFile().listFiles();
assertEquals(1, pidRefsFiles.length);
File[] cidRefsFiles = storePath.resolve("refs/cid").toFile().listFiles();
assertEquals(1, cidRefsFiles.length);
}

/**
* Check that tagObject creates pid refs file when pid already exists in cid refs file
* Check that tagObject creates a missing cid refs file
*/
@Test
public void tagObject_pidExistsInCidRefsFile() throws Exception {
public void tagObject_pidRefsFileFound_cidRefsFileNotFound() throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";

File cidRefsTmpFile = fileHashStore.writeRefsFile(pid, "cid");
fileHashStore.tagObject(pid, cid);
// Manually delete the cid refs file
Path cidRefsFilePath = fileHashStore.getExpectedPath(cid, "refs", "cid");
fileHashStore.move(cidRefsTmpFile, cidRefsFilePath.toFile(), "refs");
Files.delete(cidRefsFilePath);

fileHashStore.tagObject(pid, cid);
// Confirm that there is only 1 of each refs file
Path storePath = Paths.get(fhsProperties.getProperty("storePath"));
File[] pidRefsFiles = storePath.resolve("refs/pid").toFile().listFiles();
assertEquals(1, pidRefsFiles.length);
File[] cidRefsFiles = storePath.resolve("refs/cid").toFile().listFiles();
assertEquals(1, cidRefsFiles.length);
}

Path pidRefsFilePath = fileHashStore.getExpectedPath(pid, "refs", "pid");
assertTrue(Files.exists(pidRefsFilePath));

// Confirm that cid refs file only has 1 line
List<String> lines = Files.readAllLines(cidRefsFilePath);
int numberOfLines = lines.size();
assertEquals(numberOfLines, 1);
/**
* Check that tagObject creates a pid refs file and updates an existing cid refs file
*/
@Test
public void tagObject_pidRefsFileNotFound_cidRefsFileFound() throws Exception {
String pid = "dou.test.1";
String cid = "abcdef123456789";
fileHashStore.tagObject(pid, cid);

String pidAdditional = "another.pid.2";
fileHashStore.tagObject(pidAdditional, cid);

// Confirm missing pid refs file has been created
Path pidAdditionalRefsFilePath = fileHashStore.getExpectedPath(
pidAdditional, "refs", "pid"
);
assertTrue(Files.exists(pidAdditionalRefsFilePath));

// Check cid refs file
Path cidRefsFilePath = fileHashStore.getExpectedPath(cid, "refs", "cid");
boolean pidFoundInCidRefFiles = fileHashStore.isStringInRefsFile(
pidAdditional, cidRefsFilePath
);
assertTrue(pidFoundInCidRefFiles);

// There should be 2 pid refs file, and 1 cid refs file
Path storePath = Paths.get(fhsProperties.getProperty("storePath"));
File[] pidRefsFiles = storePath.resolve("refs/pid").toFile().listFiles();
assertEquals(2, pidRefsFiles.length);
File[] cidRefsFiles = storePath.resolve("refs/cid").toFile().listFiles();
assertEquals(1, cidRefsFiles.length);
}


/**
* Check that the cid supplied is written into the file given
*/
Expand Down

0 comments on commit f3e4fea

Please sign in to comment.