From a0e9179ff113b782fcce55649d1658b21bbb7791 Mon Sep 17 00:00:00 2001 From: Kory Draughn Date: Wed, 3 Feb 2021 08:43:42 -0500 Subject: [PATCH] squash. only hard links the latest good replica. --- .../nfsrods/vfs/IRODSVirtualFileSystem.java | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/irods-vfs-impl/src/main/java/org/irods/nfsrods/vfs/IRODSVirtualFileSystem.java b/irods-vfs-impl/src/main/java/org/irods/nfsrods/vfs/IRODSVirtualFileSystem.java index 0ed047d7..e147cfc7 100644 --- a/irods-vfs-impl/src/main/java/org/irods/nfsrods/vfs/IRODSVirtualFileSystem.java +++ b/irods-vfs-impl/src/main/java/org/irods/nfsrods/vfs/IRODSVirtualFileSystem.java @@ -77,6 +77,7 @@ import org.irods.jargon.core.pub.DataObjectAO; import org.irods.jargon.core.pub.IRODSAccessObjectFactory; import org.irods.jargon.core.pub.IRODSFileSystemAO; +import org.irods.jargon.core.pub.IRODSGenQueryExecutor; import org.irods.jargon.core.pub.RuleProcessingAO; import org.irods.jargon.core.pub.UserAO; import org.irods.jargon.core.pub.UserGroupAO; @@ -88,8 +89,13 @@ import org.irods.jargon.core.pub.io.IRODSFile; import org.irods.jargon.core.pub.io.IRODSFileFactory; import org.irods.jargon.core.pub.io.IRODSRandomAccessFile; +import org.irods.jargon.core.query.AbstractIRODSGenQuery.RowCountOptions; import org.irods.jargon.core.query.CollectionAndDataObjectListingEntry; import org.irods.jargon.core.query.CollectionAndDataObjectListingEntry.ObjectType; +import org.irods.jargon.core.query.IRODSGenQuery; +import org.irods.jargon.core.query.IRODSQueryResultRow; +import org.irods.jargon.core.query.IRODSQueryResultSet; +import org.irods.jargon.core.query.JargonQueryException; import org.irods.jargon.core.rule.IRODSRuleExecResult; import org.irods.jargon.core.rule.IrodsRuleInvocationTypeEnum; import org.irods.jargon.core.rule.RuleInvocationConfiguration; @@ -651,7 +657,7 @@ public Access checkAcl(Subject _subject, Inode _inode, int _accessMask) throws C } String path = getPath(toInodeNumber(_inode)).toString(); - + // Key (String) => ## // Value (Access) => ALLOW/DENY // Cached stat information must be scoped to the user due to the permissions @@ -852,15 +858,22 @@ public Inode link(Inode _parent, Inode _existing, String _target, Subject _subje // _parent + _target => the absolute path of the hard link. - Map jsonInput = new HashMap<>(); - jsonInput.put("operation", "hard_link_create"); - jsonInput.put("logical_path", linkTargetPath.toString()); - jsonInput.put("replica_number", "0"); - jsonInput.put("link_name", linkNamePath.toString()); - try { IRODSAccount acct = getCurrentIRODSUser().getAccount(); + Optional replicaNumber = getReplicaNumberOfLatestGoodReplica(acct, linkTargetPath); + + if (!replicaNumber.isPresent()) + { + throw new NoEntException(String.format("No good replica to link for [%s]", linkTargetPath)); + } + + Map jsonInput = new HashMap<>(); + jsonInput.put("operation", "hard_link_create"); + jsonInput.put("logical_path", linkTargetPath.toString()); + jsonInput.put("replica_number", replicaNumber.get()); + jsonInput.put("link_name", linkNamePath.toString()); + RuleProcessingAO rpao = factory_.getRuleProcessingAO(acct); RuleInvocationConfiguration ctx = new RuleInvocationConfiguration(); ctx.setIrodsRuleInvocationTypeEnum(IrodsRuleInvocationTypeEnum.OTHER); @@ -881,7 +894,7 @@ public Inode link(Inode _parent, Inode _existing, String _target, Subject _subje return toFh(newInodeNumber); } - catch (JargonException e) + catch (JargonException | JargonQueryException e) { log_.error(e.getMessage()); throw new IOException(e); @@ -1357,7 +1370,7 @@ private Stat statPath(Path _path, long _inodeNumber) throws IOException stat.setUid(userId); stat.setGid(groupId); - stat.setNlink(1); + stat.setNlink(1); // TODO: Should hard links affect this number? stat.setDev(17); stat.setIno((int) _inodeNumber); stat.setRdev(0); @@ -1611,6 +1624,33 @@ private boolean isAdministrator(String _userName) throws JargonException return user.getUserType() == UserTypeEnum.RODS_ADMIN; } + + private Optional getReplicaNumberOfLatestGoodReplica(IRODSAccount _acct, Path _logicalPath) + throws JargonException, JargonQueryException + { + // @formatter:off + String gql = String.format("select max(DATA_MODIFY_TIME) " + + "where " + + " COLL_NAME = '%s' and" + + " DATA_NAME = '%s' and" + + " DATA_REPL_STATUS = '1'", + _logicalPath.getParent(), + _logicalPath.getFileName()); + // @formatter:on + final int rowsDesired = 1; + IRODSGenQuery genQuery = IRODSGenQuery.instance(gql, rowsDesired, RowCountOptions.ROW_COUNT_FOR_THIS_RESULT); + IRODSGenQueryExecutor executor = factory_.getIRODSGenQueryExecutor(_acct); + + final int partialStartIndex = 0; + IRODSQueryResultSet resultSet = executor.executeIRODSQueryAndCloseResult(genQuery, partialStartIndex); + + for (IRODSQueryResultRow row : resultSet.getResults()) + { + return Optional.of(row.getColumn(0)); + } + + return Optional.empty(); + } private void closeCurrentConnection() throws IOException {