From 9c5fb2b267e49046fb32688f1297652d1f6f5241 Mon Sep 17 00:00:00 2001 From: Dmitry Litvintsev Date: Tue, 14 Jul 2026 09:55:11 -0500 Subject: [PATCH] transfer: restore ability to define alternative/additional checksum Motivation: ---------- Commit 3b12aa7233eb85caec1a5748b228d40f25673ce9 has introduced a side effect of theowing NPE when accessing getCellName() for JFR repoprting. Modification: ------------ Without going into much detail as to what is the root cause of NPE fuard Transfer JFR message source when cell address is unset Result: ------- upload specifying alternative checksum works: ``` $ gfal-copy -K md5:bed9c27139f6651fb9511da39210e9e8 --checksum-mode=target foo gsiftp://example.orgv/users/litvinse/foo.3 Copying file:///home/litvinse/foo [DONE] after 6s [litvinse@uqbar ~]$ echo $? 0 ``` and: ``` $ gfal-sum gsiftp://uqbar.fnal.gov/users/litvinse/foo.3 MD5 gsiftp://uqbar.fnal.gov/users/litvinse/foo.3 bed9c27139f6651fb9511da39210e9e8 $ gfal-sum gsiftp://uqbar.fnal.gov/users/litvinse/foo.3 ADLER32 gsiftp://uqbar.fnal.gov/users/litvinse/foo.3 be111976 ``` Target: trunk Request: 12.0, 11.2 Require-book: no Require-notes: yes Patch: https://rb.dcache.org/r/14724/ Acked-by: Marina Require-book: no Require-notes: yes --- .../main/java/org/dcache/util/Transfer.java | 13 ++-- .../java/org/dcache/util/TransferTest.java | 64 +++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 modules/dcache/src/test/java/org/dcache/util/TransferTest.java diff --git a/modules/dcache/src/main/java/org/dcache/util/Transfer.java b/modules/dcache/src/main/java/org/dcache/util/Transfer.java index 89fa0707dce..cecbce1ade7 100644 --- a/modules/dcache/src/main/java/org/dcache/util/Transfer.java +++ b/modules/dcache/src/main/java/org/dcache/util/Transfer.java @@ -607,6 +607,11 @@ public synchronized String getDomainName() { return _cellAddress.getCellDomainName(); } + private synchronized String getMessageEventSource() { + return _cellAddress == null ? "" : + _cellAddress.getCellName() + "@" + _cellAddress.getCellDomainName(); + } + /** * The client address is the socket address from which the transfer was initiated. */ @@ -810,7 +815,7 @@ private ListenableFuture readNameSpaceEntryAsync(boolean allowWrite, long request.setUpdateAtime(true); MessageEvent nameSpaceReadEvent = new MessageEvent(); - nameSpaceReadEvent.source = getCellName() + "@" + getDomainName(); + nameSpaceReadEvent.source = getMessageEventSource(); nameSpaceReadEvent.destination = "PnfsManager"; nameSpaceReadEvent.message = PnfsGetFileAttributes.class.getSimpleName(); nameSpaceReadEvent.begin(); @@ -985,7 +990,7 @@ public ListenableFuture selectPoolAsync(long timeout) { // init JFR event MessageEvent poolSelectEvent = new MessageEvent(); - poolSelectEvent.source = getCellName() + "@" + getDomainName(); + poolSelectEvent.source = getMessageEventSource(); poolSelectEvent.destination = "PoolManager"; poolSelectEvent.message = isWrite() ? PoolMgrSelectReadPoolMsg.class.getSimpleName() : PoolMgrSelectWritePoolMsg.class.getSimpleName(); poolSelectEvent.begin(); @@ -1089,7 +1094,7 @@ public ListenableFuture startMoverAsync(long timeout) { // init JFR event MessageEvent moverStartEvent = new MessageEvent(); - moverStartEvent.source = getCellName() + "@" + getDomainName(); + moverStartEvent.source = getMessageEventSource(); moverStartEvent.destination = pool.getName(); moverStartEvent.message = message.getClass().getSimpleName(); moverStartEvent.begin(); @@ -1156,7 +1161,7 @@ public void killMover(long millis, String explanation) { // init JFR event var killMoverEvent = new MessageEvent(); - killMoverEvent.source = getCellName() + "@" + getDomainName(); + killMoverEvent.source = getMessageEventSource(); killMoverEvent.destination = pool.getName(); killMoverEvent.message = message.getClass().getSimpleName(); diff --git a/modules/dcache/src/test/java/org/dcache/util/TransferTest.java b/modules/dcache/src/test/java/org/dcache/util/TransferTest.java new file mode 100644 index 00000000000..05aa1b80f83 --- /dev/null +++ b/modules/dcache/src/test/java/org/dcache/util/TransferTest.java @@ -0,0 +1,64 @@ +/* dCache - http://www.dcache.org/ + * + * Copyright (C) 2026 Deutsches Elektronen-Synchrotron + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.dcache.util; + +import static com.google.common.util.concurrent.Futures.immediateFuture; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import diskCacheV111.util.FsPath; +import diskCacheV111.util.PnfsHandler; +import diskCacheV111.vehicles.GenericStorageInfo; +import javax.security.auth.Subject; +import org.dcache.auth.attributes.Restrictions; +import org.dcache.cells.CellStub; +import org.dcache.namespace.FileType; +import org.dcache.vehicles.FileAttributes; +import org.dcache.vehicles.PnfsGetFileAttributes; +import org.junit.Test; + +public class TransferTest { + + @Test + public void shouldReadNamespaceEntryWithoutCellAddress() throws Exception { + CellStub stub = mock(CellStub.class); + when(stub.send(any(PnfsGetFileAttributes.class), anyLong())).thenAnswer(invocation -> { + PnfsGetFileAttributes request = invocation.getArgument(0); + PnfsGetFileAttributes reply = + new PnfsGetFileAttributes(request.getPnfsPath(), + request.getRequestedAttributes()); + FileAttributes attributes = FileAttributes.of() + .fileType(FileType.REGULAR) + .size(1L) + .storageInfo(new GenericStorageInfo()) + .build(); + reply.setFileAttributes(attributes); + return immediateFuture(reply); + }); + + Transfer transfer = new Transfer(new PnfsHandler(stub), new Subject(), + Restrictions.none(), FsPath.create("/test/path")); + + transfer.readNameSpaceEntry(false); + + verify(stub).send(any(PnfsGetFileAttributes.class), anyLong()); + } +}