Skip to content
Snippets Groups Projects
Commit a2faccb3 authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

Adapted code in preparation for file service copy call

parent b990aebb
No related branches found
No related tags found
No related merge requests found
......@@ -28,7 +28,7 @@ public class CopyService extends AbstractNodeService {
private NodeBranchService nodeBranchService;
@Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ)
public List<String> processCopyNodes(Transfer transfer, String jobId, User user) {
public String processCopyNodes(Transfer transfer, String jobId, User user) {
if (transfer.getTarget().size() != 1) {
throw new InvalidArgumentException("Invalid target size for copyNode: " + transfer.getTarget().size());
}
......@@ -39,14 +39,16 @@ public class CopyService extends AbstractNodeService {
// Get Destination Vos Path (it's in transfer direction)
String destinationPath = URIUtils.returnVosPathFromNodeURI(transfer.getDirection(), authority);
// Destination source to be returned, null if no copy was performed
String destinationCopyRoot = null;
this.validatePath(sourcePath);
this.validatePath(destinationPath);
if (sourcePath.equals(destinationPath)) {
return List.of();
return null;
}
List<String> copiedNodesPaths = null;
try {
// check source branch for read and lock it
......@@ -58,10 +60,7 @@ public class CopyService extends AbstractNodeService {
if (destShortNodeDescriptor.isPresent()) {
this.validateDestinationContainer(destShortNodeDescriptor.get(), destinationPath);
copiedNodesPaths = nodeDao.copyBranch(
sourcePath,
destinationPath + "/" + NodeUtils.getNodeName(sourcePath),
jobId);
destinationCopyRoot = destinationPath + "/" + NodeUtils.getNodeName(sourcePath);
} else {
// Check if parent exists
......@@ -70,8 +69,7 @@ public class CopyService extends AbstractNodeService {
= nodeDao.getShortNodeDescriptor(destinationParentPath, user.getName(), user.getGroups());
if (destShortNodeDescriptorParent.isPresent()) {
this.validateDestinationContainer(destShortNodeDescriptorParent.get(), destinationParentPath);
copiedNodesPaths = nodeDao.copyBranch(sourcePath,
destinationPath, jobId);
destinationCopyRoot = destinationPath;
} else {
throw new UnsupportedOperationException("Creation of destination upon copy not supported");
......@@ -79,12 +77,17 @@ public class CopyService extends AbstractNodeService {
}
nodeDao.copyBranch(
sourcePath,
destinationCopyRoot,
jobId);
} catch (CannotSerializeTransactionException ex) {
// Concurrent transactions attempted to modify this set of nodes
throw new NodeBusyException(sourcePath);
}
return copiedNodesPaths;
return destinationCopyRoot;
}
......
......@@ -40,6 +40,9 @@ public class JobService {
@Autowired
private CopyService copyService;
@Autowired
private NodeBranchService nodeBranchService;
@Autowired
private AsyncTransferService asyncTransfService;
......@@ -180,7 +183,8 @@ public class JobService {
copyService.processCopyNodes(transfer, jobSummary.getJobId(), user);
// add file service copy logic
job.setPhase(ExecutionPhase.COMPLETED);
// the file service part will unlock nodes and set job phase
// to completed
});
});
}
......
......@@ -64,4 +64,8 @@ public class NodeBranchService {
}
public void unlockNodes(String jobId) {
nodeDao.releaseBusyNodesByJobId(jobId);
}
}
......@@ -344,7 +344,7 @@ public class NodeDAO {
});
}
public List<String> copyBranch(String sourceVosPath, String destVosPath, String jobId) {
public void copyBranch(String sourceVosPath, String destVosPath, String jobId) {
String destVosParentPath = NodeUtils.getParentPath(destVosPath);
String destName = NodeUtils.getNodeName(destVosPath);
......@@ -376,8 +376,6 @@ public class NodeDAO {
+ "name, type, location_id, creator_id, group_write, group_read, is_public, ?\n"
+ "FROM copied_nodes_paths\n";
String returning = "RETURNING get_vos_path(node_id) AS returning_path";
String sql = parentInsert
+ "WITH RECURSIVE path_prefix AS ("
+ ctePathPrefix + "),\n"
......@@ -385,19 +383,15 @@ public class NodeDAO {
+ cteCopiedNodes + "),\n"
+ "copied_nodes_paths AS ("
+ cteCopiedNodesPaths + ")\n"
+ parentSelect
+ returning;
+ parentSelect;
return jdbcTemplate.query(conn -> {
jdbcTemplate.update(conn -> {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, destVosParentPath);
ps.setString(2, destName);
ps.setString(3, sourceVosPath);
ps.setString(4, jobId);
return ps;
}, (rs, row) -> {
return rs.getString("returning_path");
});
}
......@@ -424,6 +418,16 @@ public class NodeDAO {
});
}
public void releaseBusyNodesByJobId(String jobId) {
String sql = "UPDATE node SET job_id = NULL WHERE job_id = ?";
jdbcTemplate.update(conn -> {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, jobId);
return ps;
});
}
public boolean isBranchWritable(long parentNodeId, String userId, List<String> userGroups) {
String sql = "SELECT COUNT(c.node_id) = 0 "
......
......@@ -15,6 +15,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import net.ivoa.xml.vospace.v2.Transfer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
......@@ -151,7 +152,10 @@ public class CopyServiceTest {
assertTrue(destId.isPresent());
// copy
copyService.processCopyNodes(getTransfer("/test3/m1", "/test4"), "job_pippo", user);
String copyDestination
= copyService.processCopyNodes(getTransfer("/test3/m1", "/test4"), "job_pippo", user);
assertEquals("/test4/m1", copyDestination);
// source has been moved
Optional<Long> oldSourceId = nodeDao.getNodeId("/test3/m1");
......@@ -183,7 +187,10 @@ public class CopyServiceTest {
assertTrue(destId.isEmpty());
// copy
copyService.processCopyNodes(getTransfer("/test3/m1/m2", "/test3/m1/m2_copy"), "job_pippo", user);
String copyDestination
= copyService.processCopyNodes(getTransfer("/test3/m1/m2", "/test3/m1/m2_copy"), "job_pippo", user);
assertEquals("/test3/m1/m2_copy", copyDestination);
// source has been moved
Optional<Long> oldSourceId = nodeDao.getNodeId("/test3/m1");
......
......@@ -49,6 +49,7 @@ public class NodeDAOTest {
ReflectionTestUtils.setField(dao, "authority", AUTHORITY);
}
@Test
public void testCreateNode() {
DataNode dataNode = new DataNode();
......@@ -282,6 +283,7 @@ public class NodeDAOTest {
}
@Test
public void testCopyNodeBranch() {
// Let's copy /test3/m1 to /test3/group1
......@@ -294,14 +296,8 @@ public class NodeDAOTest {
Optional<Long> optDestParentId = dao.getNodeId("/test3/group1");
assertTrue(optDestParentId.isPresent());
List<String> returnedPaths =
dao.copyBranch("/test3/m1", "/test3/group1/copy_of_m1", "pippo");
assertEquals(2, returnedPaths.size());
assertTrue(returnedPaths.containsAll(
List.of("/test3/group1/copy_of_m1",
"/test3/group1/copy_of_m1/m2")));
Optional<Long> resultId = dao.getNodeId("/test3/group1/copy_of_m1");
assertTrue(resultId.isPresent());
......@@ -471,6 +467,29 @@ public class NodeDAOTest {
assertEquals("f4", dao.getNodeOsName("/test2/f4"));
}
@Test
public void testReleaseNodesByJobId(){
Optional<Long> optId = dao.getNodeId("/test3/m1");
assertTrue(optId.isPresent());
assertFalse(dao.isBranchBusy(optId.get()));
dao.setBranchJobId(optId.get(), "pippo1");
assertTrue(dao.isBranchBusy(optId.get()));
Optional<Long> childId = dao.getNodeId("/test3/m1/m2");
assertTrue(childId.isPresent());
assertTrue(dao.isBranchBusy(childId.get()));
dao.releaseBusyNodesByJobId("pippo1");
assertFalse(dao.isBranchBusy(optId.get()));
assertFalse(dao.isBranchBusy((childId.get())));
}
private Property getProperty(String uri, String value) {
Property property = new Property();
property.setUri(uri);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment