From d8c438144bf0ab86dd8f4c9e0f08f69da92b2d07 Mon Sep 17 00:00:00 2001 From: "Ole V. Villumsen" Date: Fri, 22 Jul 2022 11:13:31 +0200 Subject: [PATCH 1/8] Update repository settings version; minor text polish --- .../mediator/CollectionBasedConversationMediator.java | 8 ++++---- .../collector/IntegrityEventCompleteAwaiter.java | 2 +- pom.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java index 25a3ca891..1baae5e1d 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java +++ b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java @@ -51,7 +51,7 @@ public class CollectionBasedConversationMediator implements ConversationMediator private final Logger log = LoggerFactory.getLogger(getClass()); private final Map conversations; private final Settings settings; - private static final Boolean TIMER_IS_DAEMON = true; + private static final boolean TIMER_IS_DAEMON = true; private static final String NAME_OF_TIMER = "Collection based conversation timer"; /** * The timer used to schedule cleaning of conversations. @@ -136,10 +136,10 @@ public void onMessage(Message message, MessageContext messageContext) { } /** - * Will clean out obsolete conversations in each run. An obsolete conversation is a conversation which satisfies on - * of the following criterias:
    + * Will clean out obsolete conversations in each run. An obsolete conversation is a conversation which satisfies ony + * of the following criteria:
      *
    1. Returns true for the hasEnded() method. - *
    2. Is older than the conversationTImeout limit allows. + *
    3. Is older than the conversationTimeout limit allows. *
    *

    * A copy of the current conversations is created before running through the conversations to avoid having to lock diff --git a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java index 144a40f89..3d97b852b 100644 --- a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java +++ b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java @@ -71,7 +71,7 @@ public void handleEvent(OperationEvent event) { /** * Retrieves the final event when the operation finishes. The final event is awaited for 'timeout' amount - * of milliseconds. If no final events has occurred, then an InterruptedException is thrown. + * of milliseconds. If no final events has occurred, null is returned. * * @return The final event. */ diff --git a/pom.xml b/pom.xml index 53b04b878..3aa828608 100644 --- a/pom.xml +++ b/pom.xml @@ -496,7 +496,7 @@ process-classes 31 - 13 + 14-SNAPSHOT 10.14.2.0 5.16.4 3.3.6 From aabcc07ba921736999ecdf09c3db7d4595b30ec3 Mon Sep 17 00:00:00 2001 From: "Ole V. Villumsen" Date: Fri, 29 Jul 2022 14:44:09 +0200 Subject: [PATCH 2/8] BITMAG-992 Prefer the new XxDuration settings in repository settings over the old ones in milliseconds --- .../client/conversation/FinishedState.java | 5 +- .../GeneralConversationState.java | 12 +- .../client/conversation/IdentifyingState.java | 6 +- .../PerformingOperationState.java | 11 +- .../commandline/CommandLineClient.java | 6 +- .../clients/PagingGetChecksumsClient.java | 8 +- .../clients/PagingGetFileIDsClient.java | 8 +- .../eventhandler/CompleteEventAwaiter.java | 18 +-- .../GetChecksumsEventHandler.java | 4 +- .../eventhandler/GetFileIDsEventHandler.java | 4 +- .../eventhandler/PagingEventHandler.java | 19 +-- .../AuditTrailClientComponentTest.java | 27 +++-- .../getfile/GetFileClientComponentTest.java | 67 ++++++----- .../GetStatusClientComponentTest.java | 26 ++-- .../client/DefaultClientTest.java | 21 +++- .../DeleteFileClientComponentTest.java | 13 +- .../putfile/PutFileClientComponentTest.java | 32 +++-- .../ReplaceFileClientComponentTest.java | 13 +- .../common/settings/Settings.java | 79 +++++++++++- .../common/utils/CountAndTimeUnit.java | 35 ++++++ .../bitrepository/common/utils/TimeUtils.java | 75 +++++++++++- .../common/settings/SettingsTest.java | 113 ++++++++++++++++++ .../common/utils/TimeUtilsTest.java | 65 +++++++++- .../IntegrityCollectorEventHandler.java | 23 ++-- .../IntegrityEventCompleteAwaiter.java | 12 +- .../collector/SimpleChecksumEventHandler.java | 23 ++-- .../workflow/step/GetChecksumForFileStep.java | 6 +- .../workflow/step/UpdateChecksumsStep.java | 6 +- .../workflow/step/UpdateFileIDsStep.java | 6 +- 29 files changed, 589 insertions(+), 154 deletions(-) create mode 100644 bitrepository-core/src/main/java/org/bitrepository/common/utils/CountAndTimeUnit.java create mode 100644 bitrepository-core/src/test/java/org/bitrepository/common/settings/SettingsTest.java diff --git a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/FinishedState.java b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/FinishedState.java index f30a6ef79..fbee81d00 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/FinishedState.java +++ b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/FinishedState.java @@ -27,6 +27,7 @@ import org.bitrepository.bitrepositorymessages.MessageResponse; import org.bitrepository.common.exceptions.UnableToFinishException; +import java.time.Duration; import java.util.LinkedList; /** @@ -54,8 +55,8 @@ protected GeneralConversationState completeState() { } @Override - protected long getTimeoutValue() { - return 0; + protected Duration getTimeoutValue() { + return Duration.ZERO; } @Override diff --git a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java index 96d9b939d..78bf7902d 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java +++ b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java @@ -31,10 +31,13 @@ import org.bitrepository.client.exceptions.UnexpectedResponseException; import org.bitrepository.common.DefaultThreadFactory; import org.bitrepository.common.exceptions.UnableToFinishException; +import org.bitrepository.common.utils.CountAndTimeUnit; +import org.bitrepository.common.utils.TimeUtils; import org.bitrepository.protocol.ProtocolVersionLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.Collection; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -71,8 +74,9 @@ protected GeneralConversationState(Collection expectedContributors) { public void start() { try { if (!responseStatus.getOutstandingComponents().isEmpty()) { - if (getTimeoutValue() > 0) { - scheduledTimeout = timer.schedule(new TimeoutHandler(), getTimeoutValue(), TimeUnit.MILLISECONDS); + if (getTimeoutValue().compareTo(Duration.ZERO) > 0) { // From Java 18 use: getTimeoutValue().isPositive() + CountAndTimeUnit delay = TimeUtils.durationToCountAndTimeUnit(getTimeoutValue()); + scheduledTimeout = timer.schedule(new TimeoutHandler(), delay.getCount(), delay.getUnit()); } sendRequest(); } else { @@ -217,9 +221,9 @@ protected abstract boolean processMessage(MessageResponse response) throws Unexp /** * Gives access to the concrete timeout for the state. - * @return the number of milliseconds before timeout + * @return the duration before timeout */ - protected abstract long getTimeoutValue(); + protected abstract Duration getTimeoutValue(); /** * @return The informative naming of the process this state is performing. Used for logging. Examples are 'Delete files', diff --git a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/IdentifyingState.java b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/IdentifyingState.java index 8e596e76a..c12d6d6ad 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/IdentifyingState.java +++ b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/IdentifyingState.java @@ -28,6 +28,7 @@ import org.bitrepository.client.exceptions.UnexpectedResponseException; import org.bitrepository.common.exceptions.UnableToFinishException; +import java.time.Duration; import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -79,9 +80,8 @@ protected final GeneralConversationState completeState() throws UnableToFinishEx } @Override - protected long getTimeoutValue() { - return getContext().getSettings().getRepositorySettings().getClientSettings().getIdentificationTimeout() - .longValue(); + protected Duration getTimeoutValue() { + return getContext().getSettings().getIdentificationTimeout(); } /** diff --git a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/PerformingOperationState.java b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/PerformingOperationState.java index cb68ac984..7fad2d5a9 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/PerformingOperationState.java +++ b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/PerformingOperationState.java @@ -26,7 +26,9 @@ import org.bitrepository.client.conversation.selector.SelectedComponentInfo; import org.bitrepository.client.exceptions.UnexpectedResponseException; import org.bitrepository.common.exceptions.UnableToFinishException; +import org.bitrepository.common.utils.TimeUtils; +import java.time.Duration; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -79,14 +81,15 @@ protected boolean processMessage(MessageResponse msg) throws UnableToFinishExcep @Override protected void logStateTimeout() throws UnableToFinishException { - throw new UnableToFinishException( - "Failed to receive responses from all contributors before timeout(" + getTimeoutValue() + "ms). Missing contributors " + + throw new UnableToFinishException("Failed to receive responses from all contributors before timeout (" + + TimeUtils.durationToHuman(getTimeoutValue()) + + "). Missing contributors " + getOutstandingComponents()); } @Override - protected long getTimeoutValue() { - return getContext().getSettings().getRepositorySettings().getClientSettings().getOperationTimeout().longValue(); + protected Duration getTimeoutValue() { + return getContext().getSettings().getOperationTimeout(); } @Override diff --git a/bitrepository-client/src/main/java/org/bitrepository/commandline/CommandLineClient.java b/bitrepository-client/src/main/java/org/bitrepository/commandline/CommandLineClient.java index eff5dba1d..995a2f2ab 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/commandline/CommandLineClient.java +++ b/bitrepository-client/src/main/java/org/bitrepository/commandline/CommandLineClient.java @@ -47,6 +47,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.security.NoSuchAlgorithmException; +import java.time.Duration; import java.util.List; /** @@ -208,9 +209,8 @@ protected List getPillarIDs() { /** * @return The timeout to use for performing the full operation. */ - protected long getTimeout() { - return settings.getRepositorySettings().getClientSettings().getIdentificationTimeout().longValue() + - settings.getRepositorySettings().getClientSettings().getOperationTimeout().longValue(); + protected Duration getTimeout() { + return settings.getIdentificationTimeout().plus(settings.getOperationTimeout()); } /** diff --git a/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetChecksumsClient.java b/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetChecksumsClient.java index 6609c5d12..c3bc859da 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetChecksumsClient.java +++ b/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetChecksumsClient.java @@ -30,9 +30,11 @@ import org.bitrepository.commandline.outputformatter.GetChecksumsOutputFormatter; import org.bitrepository.commandline.resultmodel.GetChecksumsResultModel; +import java.time.Duration; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Objects; /** * Wrapper class for GetChecksumClient to handle paging through large result sets @@ -42,13 +44,13 @@ public class PagingGetChecksumsClient { private GetChecksumsResultModel model; private final GetChecksumsOutputFormatter outputFormatter; private final OutputHandler outputHandler; - private final long timeout; + private final Duration timeout; private final int pageSize; - public PagingGetChecksumsClient(GetChecksumsClient client, long timeout, int pageSize, GetChecksumsOutputFormatter outputFormatter, + public PagingGetChecksumsClient(GetChecksumsClient client, Duration timeout, int pageSize, GetChecksumsOutputFormatter outputFormatter, OutputHandler outputHandler) { this.client = client; - this.timeout = timeout; + this.timeout = Objects.requireNonNull(timeout, "timeout"); this.pageSize = pageSize; this.outputFormatter = outputFormatter; this.outputHandler = outputHandler; diff --git a/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetFileIDsClient.java b/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetFileIDsClient.java index eca451cc5..161790c7a 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetFileIDsClient.java +++ b/bitrepository-client/src/main/java/org/bitrepository/commandline/clients/PagingGetFileIDsClient.java @@ -29,9 +29,11 @@ import org.bitrepository.commandline.outputformatter.GetFileIDsOutputFormatter; import org.bitrepository.commandline.resultmodel.GetFileIDsResultModel; +import java.time.Duration; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Objects; /** * Wrapper class for GetFileIDsClient to handle paging through large result sets @@ -41,13 +43,13 @@ public class PagingGetFileIDsClient { private GetFileIDsResultModel model; private final GetFileIDsOutputFormatter outputFormatter; private final OutputHandler outputHandler; - private final long timeout; + private final Duration timeout; private final int pageSize; - public PagingGetFileIDsClient(GetFileIDsClient client, long timeout, int pageSize, GetFileIDsOutputFormatter outputFormatter, + public PagingGetFileIDsClient(GetFileIDsClient client, Duration timeout, int pageSize, GetFileIDsOutputFormatter outputFormatter, OutputHandler outputHandler) { this.client = client; - this.timeout = timeout; + this.timeout = Objects.requireNonNull(timeout, "timeout"); this.pageSize = pageSize; this.outputFormatter = outputFormatter; this.outputHandler = outputHandler; diff --git a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/CompleteEventAwaiter.java b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/CompleteEventAwaiter.java index 1e40dabfd..793c528ae 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/CompleteEventAwaiter.java +++ b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/CompleteEventAwaiter.java @@ -26,7 +26,10 @@ import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType; import org.bitrepository.commandline.output.OutputHandler; import org.bitrepository.common.settings.Settings; +import org.bitrepository.common.utils.CountAndTimeUnit; +import org.bitrepository.common.utils.TimeUtils; +import java.time.Duration; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -39,7 +42,7 @@ public abstract class CompleteEventAwaiter implements EventHandler { /** * The amount of milliseconds before the results are required. */ - private final Long timeout; + private final Duration timeout; /** * The handler of the output for this event handler. */ @@ -55,8 +58,7 @@ public abstract class CompleteEventAwaiter implements EventHandler { * @param outputHandler The {@link OutputHandler} for handling outputting results */ public CompleteEventAwaiter(Settings settings, OutputHandler outputHandler) { - this.timeout = settings.getRepositorySettings().getClientSettings().getIdentificationTimeout().longValue() - + settings.getRepositorySettings().getClientSettings().getOperationTimeout().longValue(); + this.timeout = settings.getIdentificationTimeout().plus(settings.getOperationTimeout()); this.output = outputHandler; } @@ -78,14 +80,16 @@ public void handleEvent(OperationEvent event) { public abstract void handleComponentComplete(OperationEvent event); /** - * Retrieves the final event when the operation finishes. The final event is awaited for 'timeout' amount - * of milliseconds. If no final events has occurred, then an InterruptedException is thrown. + * Retrieves the final event when the operation finishes. + * The final event is awaited for 'timeout'. If no final events has occurred, null is returned. * - * @return The final event. + * @return The final event or null if none has occurred. + * @throws IllegalStateException if interrupted while waiting */ public OperationEvent getFinish() { try { - return finalEventQueue.poll(timeout, TimeUnit.MILLISECONDS); + CountAndTimeUnit pollTimeout = TimeUtils.durationToCountAndTimeUnit(timeout); + return finalEventQueue.poll(pollTimeout.getCount(), pollTimeout.getUnit()); } catch (InterruptedException e) { throw new IllegalStateException("Interrupted while waiting for the final response.", e); } diff --git a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetChecksumsEventHandler.java b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetChecksumsEventHandler.java index 4b2808976..673134252 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetChecksumsEventHandler.java +++ b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetChecksumsEventHandler.java @@ -26,6 +26,8 @@ import org.bitrepository.commandline.output.OutputHandler; import org.bitrepository.commandline.resultmodel.GetChecksumsResultModel; +import java.time.Duration; + /** * Event handler for paging through GetChecksums results */ @@ -33,7 +35,7 @@ public class GetChecksumsEventHandler extends PagingEventHandler { private final GetChecksumsResultModel model; - public GetChecksumsEventHandler(GetChecksumsResultModel model, Long timeout, OutputHandler outputHandler) { + public GetChecksumsEventHandler(GetChecksumsResultModel model, Duration timeout, OutputHandler outputHandler) { super(timeout, outputHandler); this.model = model; } diff --git a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetFileIDsEventHandler.java b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetFileIDsEventHandler.java index 58927d1ca..65e967cb6 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetFileIDsEventHandler.java +++ b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/GetFileIDsEventHandler.java @@ -26,13 +26,15 @@ import org.bitrepository.commandline.output.OutputHandler; import org.bitrepository.commandline.resultmodel.GetFileIDsResultModel; +import java.time.Duration; + /** * Event handler for paging through GetFileIDs results */ public class GetFileIDsEventHandler extends PagingEventHandler { private final GetFileIDsResultModel model; - public GetFileIDsEventHandler(GetFileIDsResultModel model, Long timeout, OutputHandler outputHandler) { + public GetFileIDsEventHandler(GetFileIDsResultModel model, Duration timeout, OutputHandler outputHandler) { super(timeout, outputHandler); this.model = model; } diff --git a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/PagingEventHandler.java b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/PagingEventHandler.java index e8d31a170..0b34ff188 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/PagingEventHandler.java +++ b/bitrepository-client/src/main/java/org/bitrepository/commandline/eventhandler/PagingEventHandler.java @@ -25,9 +25,13 @@ import org.bitrepository.client.eventhandler.OperationEvent; import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType; import org.bitrepository.commandline.output.OutputHandler; +import org.bitrepository.common.utils.CountAndTimeUnit; +import org.bitrepository.common.utils.TimeUtils; +import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -36,15 +40,15 @@ * Event handler for operations that need paging functionality. */ public abstract class PagingEventHandler implements EventHandler { - private final Long timeout; + private final Duration timeout; private final BlockingQueue finalEventQueue = new LinkedBlockingQueue<>(1); protected List pillarsWithPartialResults = new ArrayList<>(); private final OutputHandler outputHandler; - public PagingEventHandler(Long timeout, OutputHandler outputHandler) { - this.timeout = timeout; + public PagingEventHandler(Duration timeout, OutputHandler outputHandler) { + this.timeout = Objects.requireNonNull(timeout, "timeout"); this.outputHandler = outputHandler; } @@ -62,14 +66,15 @@ public void handleEvent(OperationEvent event) { } /** - * Retrieves the final event when the operation finishes. The final event is awaited for 'timeout' amount - * of milliseconds. If no final events has occurred, then an IllegalStateException is thrown. + * Retrieves the final event when the operation finishes. + * The final event is awaited for 'timeout'. If no final events has occurred, then null is returned. * - * @return The final event. + * @return The final event or null if none has occurred. */ public OperationEvent getFinish() { try { - return finalEventQueue.poll(timeout, TimeUnit.MILLISECONDS); + CountAndTimeUnit pollTimeout = TimeUtils.durationToCountAndTimeUnit(timeout); + return finalEventQueue.poll(pollTimeout.getCount(), pollTimeout.getUnit()); } catch (InterruptedException e) { throw new IllegalStateException("Interrupted while waiting for the final response.", e); } diff --git a/bitrepository-client/src/test/java/org/bitrepository/access/getaudittrails/AuditTrailClientComponentTest.java b/bitrepository-client/src/test/java/org/bitrepository/access/getaudittrails/AuditTrailClientComponentTest.java index 3ec4e8bf3..e16eeda11 100644 --- a/bitrepository-client/src/test/java/org/bitrepository/access/getaudittrails/AuditTrailClientComponentTest.java +++ b/bitrepository-client/src/test/java/org/bitrepository/access/getaudittrails/AuditTrailClientComponentTest.java @@ -46,6 +46,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; import java.math.BigInteger; import static org.testng.Assert.assertEquals; @@ -56,9 +58,10 @@ */ public class AuditTrailClientComponentTest extends DefaultClientTest { private GetAuditTrailsMessageFactory testMessageFactory; + private DatatypeFactory datatypeFactory; @BeforeMethod(alwaysRun=true) - public void beforeMethodSetup() throws Exception { + public void beforeMethodSetup() throws DatatypeConfigurationException { testMessageFactory = new GetAuditTrailsMessageFactory(settingsForTestClient.getComponentID()); Collection c = settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0); @@ -71,10 +74,12 @@ public void beforeMethodSetup() throws Exception { settingsForCUT.getRepositorySettings().getCollections().getCollection().add(c); settingsForCUT.getRepositorySettings().getGetAuditTrailSettings().getNonPillarContributorIDs().clear(); + + datatypeFactory = DatatypeFactory.newInstance(); } @Test(groups = {"regressiontest"}) - public void verifyAuditTrailClientFromFactory() throws Exception { + public void verifyAuditTrailClientFromFactory() { Assert.assertTrue(AccessComponentFactory.getInstance().createAuditTrailClient( settingsForCUT, securityManager, settingsForTestClient.getComponentID()) instanceof ConversationBasedAuditTrailClient, @@ -84,7 +89,7 @@ public void verifyAuditTrailClientFromFactory() throws Exception { @Test(groups = {"regressiontest"}) public void getAllAuditTrailsTest() throws InterruptedException { - addDescription("Tests the simplest case of getting all audit trail event for all contributers."); + addDescription("Tests the simplest case of getting all audit trail event for all contributors."); addStep("Create a AuditTrailClient.", ""); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); @@ -92,7 +97,7 @@ public void getAllAuditTrailsTest() throws InterruptedException { addStep("Retrieve all audit trails from the collection by calling with a null componentQueries array", "This should be interpreted as a request for all audit trails from all the collection settings " + - "defined contributers."); + "defined contributors."); client.getAuditTrails(collectionID, null, DEFAULT_FILE_ID, null, testEventHandler, null); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEvent.OperationEventType.IDENTIFY_REQUEST_SENT); @@ -232,7 +237,7 @@ public void getSomeAuditTrailsTest() throws InterruptedException { @Test(groups = {"regressiontest"}) public void negativeGetAuditTrailsResponseTest() throws InterruptedException { addDescription("Verify that the GetAuditTrail client works correct when receiving a negative " + - "GetAuditTrails response from one contributers."); + "GetAuditTrails response from one contributors."); addStep("Create a AuditTrailClient.", ""); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); @@ -240,7 +245,7 @@ public void negativeGetAuditTrailsResponseTest() throws InterruptedException { addStep("Retrieve all audit trails from the collection by calling with a null componentQueries array", "This should be interpreted as a request for all audit trails from all the collection settings " + - "defined contributers."); + "defined contributors."); client.getAuditTrails(collectionID, null, null, null, testEventHandler, null); IdentifyContributorsForGetAuditTrailsRequest identifyRequest = collectionReceiver.waitForMessage(IdentifyContributorsForGetAuditTrailsRequest.class); @@ -314,7 +319,7 @@ public void progressEventsTest() throws InterruptedException { addStep("Retrieve all audit trails from the collection by calling with a null componentQueries array", "This should be interpreted as a request for all audit trails from all the collection settings " + - "defined contributers."); + "defined contributors."); client.getAuditTrails(collectionID, null, null, null, testEventHandler, null); IdentifyContributorsForGetAuditTrailsRequest identifyRequest = collectionReceiver.waitForMessage(IdentifyContributorsForGetAuditTrailsRequest.class); @@ -376,11 +381,11 @@ public void progressEventsTest() throws InterruptedException { @Test(groups = {"regressiontest"}) public void incompleteSetOfFinalResponsesTest() throws Exception { addDescription("Verify that the GetAuditTrail client works correct without receiving responses from all " + - "contributers."); + "contributors."); addStep("Configure 500 ms second timeout for the operation itself. " + - "The default 2 contributers collection is used", ""); + "The default 2 contributors collection is used", ""); - settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeout(BigInteger.valueOf(500)); + settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeoutDuration(datatypeFactory.newDuration(500)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); AuditTrailClient client = createAuditTrailClient(); @@ -421,7 +426,7 @@ public void noFinalResponsesTest() throws Exception { addDescription("Tests the the AuditTrailClient handles lack of Final Responses gracefully "); addStep("Set a 100 ms timeout for the operation.", ""); - settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeout(BigInteger.valueOf(100)); + settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeoutDuration(datatypeFactory.newDuration(100)); AuditTrailClient client = createAuditTrailClient(); addStep("Make the client ask for all audit trails.", diff --git a/bitrepository-client/src/test/java/org/bitrepository/access/getfile/GetFileClientComponentTest.java b/bitrepository-client/src/test/java/org/bitrepository/access/getfile/GetFileClientComponentTest.java index 4bd294ad8..663b11d7a 100644 --- a/bitrepository-client/src/test/java/org/bitrepository/access/getfile/GetFileClientComponentTest.java +++ b/bitrepository-client/src/test/java/org/bitrepository/access/getfile/GetFileClientComponentTest.java @@ -39,8 +39,11 @@ import org.bitrepository.client.eventhandler.IdentificationCompleteEvent; import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType; import org.testng.Assert; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; import java.math.BigInteger; import java.net.URL; @@ -51,7 +54,14 @@ */ public class GetFileClientComponentTest extends AbstractGetFileClientTest { - private static FilePart NO_FILE_PART = null; + private static final FilePart NO_FILE_PART = null; + + private DatatypeFactory datatypeFactory; + + @BeforeMethod(alwaysRun = true) + public void setUpFactory() throws DatatypeConfigurationException { + datatypeFactory = DatatypeFactory.newInstance(); + } @Test(groups = {"regressiontest"}) public void verifyGetFileClientFromFactory() { @@ -89,7 +99,7 @@ public void getFileFromSpecificPillar() throws Exception { messageBus.sendMessage(identifyResponse1); addStep("Send a response from pillar2", "A COMPONENT_IDENTIFIED event should be generated for pillar2 " + - "followed by a IDENTIFICATION_COMPLETE event. " + + "followed by an IDENTIFICATION_COMPLETE event. " + "The client should then proceed to requesting the file from pillar2 by sending a GetFileRequest with " + "the correct and parameters" + "generating a REQUEST_SENT event."); @@ -154,8 +164,8 @@ public void getFileFromSpecificPillarWithFilePart() throws Exception { "A IdentifyPillarsForGetFileRequest will be sent to the pillar."); client.getFileFromSpecificPillar(collectionID, DEFAULT_FILE_ID, filePart, httpServerConfiguration.getURL(DEFAULT_FILE_ID), chosenPillar, testEventHandler, null); - IdentifyPillarsForGetFileRequest receivedIdentifyRequestMessage = null; - receivedIdentifyRequestMessage = collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); + IdentifyPillarsForGetFileRequest receivedIdentifyRequestMessage = + collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_REQUEST_SENT); addStep("The pillar sends a response to the identify message.", @@ -215,7 +225,7 @@ public void chooseFastestPillarGetFileClient() throws Exception { "It should be possible to change the values of the configurations."); addStep("Make the GetClient ask for fastest pillar.", - "It should send message to identify which pillars and a IdentifyPillarsRequestSent notification should be generated."); + "It should send message to identify which pillars and an IdentifyPillarsRequestSent notification should be generated."); client.getFileFromFastestPillar(collectionID, DEFAULT_FILE_ID, NO_FILE_PART, httpServerConfiguration.getURL(DEFAULT_FILE_ID), testEventHandler, null); @@ -266,11 +276,12 @@ public void chooseFastestPillarGetFileClient() throws Exception { public void getFileClientWithIdentifyTimeout() throws Exception { addDescription("Verify that the GetFile works correct without receiving responses from all pillars."); addFixture("Set the identification timeout to 500ms"); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(500)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(500)); addStep("Call getFile form fastest pillar.", - "A IDENTIFY_REQUEST_SENT should be generate and a identification request should be sent."); + "A IDENTIFY_REQUEST_SENT should be generate and an identification request should be sent."); GetFileClient client = createGetFileClient(); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); client.getFileFromFastestPillar(collectionID, DEFAULT_FILE_ID, NO_FILE_PART, @@ -280,7 +291,7 @@ public void getFileClientWithIdentifyTimeout() throws Exception { collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_REQUEST_SENT); - addStep("Send a identification response from pillar1.", + addStep("Send an identification response from pillar1.", "A COMPONENT_IDENTIFIED event should be generated."); IdentifyPillarsForGetFileResponse identificationResponse1 = messageFactory.createIdentifyPillarsForGetFileResponse( @@ -289,7 +300,7 @@ public void getFileClientWithIdentifyTimeout() throws Exception { assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_IDENTIFIED); addStep("Wait 1 second.", - "A IDENTIFY_TIMEOUT event should be generated, followed by a IDENTIFICATION_COMPLETE."); + "A IDENTIFY_TIMEOUT event should be generated, followed by an IDENTIFICATION_COMPLETE."); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_TIMEOUT); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_FAILED); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFICATION_COMPLETE); @@ -314,7 +325,8 @@ public void noIdentifyResponse() throws Exception { addDescription("Tests the the GetFileClient handles lack of IdentifyPillarResponses gracefully "); addStep("Set a 500 ms timeout for identifying pillar.", ""); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(500)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(500)); GetFileClient client = createGetFileClient(); addStep("Make the GetClient ask for fastest pillar.", @@ -349,8 +361,7 @@ public void conversationTimeout() throws Exception { client.getFileFromSpecificPillar(collectionID, DEFAULT_FILE_ID, NO_FILE_PART, httpServerConfiguration.getURL(DEFAULT_FILE_ID), PILLAR1_ID, testEventHandler, null); - IdentifyPillarsForGetFileRequest receivedIdentifyRequestMessage = null; - receivedIdentifyRequestMessage = + IdentifyPillarsForGetFileRequest receivedIdentifyRequestMessage = collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_REQUEST_SENT); @@ -393,7 +404,7 @@ public void testNoSuchFileSpecificPillar() throws Exception { assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_REQUEST_SENT); addStep("The specified pillars sends a FILE_NOT_FOUND response", - "The client should generate 1 PillarIdentified event followed by a operation failed event."); + "The client should generate 1 PillarIdentified event followed by an operation failed event."); IdentifyPillarsForGetFileResponse pillar1Response = messageFactory.createIdentifyPillarsForGetFileResponse( receivedIdentifyRequestMessage, PILLAR1_ID, pillar1DestinationId); pillar1Response.getResponseInfo().setResponseCode(ResponseCode.FILE_NOT_FOUND_FAILURE); @@ -417,7 +428,7 @@ public void testNoSuchFileMultiplePillars() throws Exception { addStep("Use the default 2 pillars.", ""); addStep("Call getFileFromFastestPillar.", - "An identify request should be sent and a IdentifyPillarsRequestSent event should be generate"); + "An identify request should be sent and an IdentifyPillarsRequestSent event should be generate"); client.getFileFromFastestPillar(collectionID, fileName, NO_FILE_PART, url, testEventHandler, null); IdentifyPillarsForGetFileRequest receivedIdentifyRequestMessage = collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); @@ -450,7 +461,7 @@ public void getFileClientWithChecksumPillarInvolved() throws Exception { addDescription("Verify that the GetFile works correctly when a checksum pillar respond."); addStep("Call getFile form fastest pillar.", - "A IDENTIFY_REQUEST_SENT should be generate and a identification request should be sent."); + "A IDENTIFY_REQUEST_SENT should be generate and an identification request should be sent."); GetFileClient client = createGetFileClient(); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); client.getFileFromFastestPillar(collectionID, DEFAULT_FILE_ID, NO_FILE_PART, @@ -460,7 +471,7 @@ public void getFileClientWithChecksumPillarInvolved() throws Exception { collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_REQUEST_SENT); - addStep("Send a identification response from pillar1 with a REQUEST_NOT_SUPPORTED response code.", + addStep("Send an identification response from pillar1 with a REQUEST_NOT_SUPPORTED response code.", "No events should be generated."); IdentifyPillarsForGetFileResponse identificationResponse1 = messageFactory.createIdentifyPillarsForGetFileResponse( @@ -469,8 +480,8 @@ public void getFileClientWithChecksumPillarInvolved() throws Exception { messageBus.sendMessage(identificationResponse1); testEventHandler.verifyNoEventsAreReceived(); - addStep("Send a identification response from pillar2 with a IDENTIFICATION_POSITIVE response code .", - "A component COMPONENT_IDENTIFIED event shouæd be generated followed by a IDENTIFICATION_COMPLETE."); + addStep("Send an identification response from pillar2 with an IDENTIFICATION_POSITIVE response code .", + "A component COMPONENT_IDENTIFIED event should be generated followed by an IDENTIFICATION_COMPLETE."); IdentifyPillarsForGetFileResponse identificationResponse2 = messageFactory.createIdentifyPillarsForGetFileResponse( receivedIdentifyRequestMessage, PILLAR2_ID, pillar2DestinationId); messageBus.sendMessage(identificationResponse2); @@ -497,7 +508,7 @@ public void singleComponentFailureDuringIdentify() throws Exception { "during the identify phase."); addStep("Call getFile from the fastest pillar.", - "A IDENTIFY_REQUEST_SENT should be generate and a identification request should be sent."); + "A IDENTIFY_REQUEST_SENT should be generate and an identification request should be sent."); GetFileClient client = createGetFileClient(); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); client.getFileFromFastestPillar(collectionID, DEFAULT_FILE_ID, NO_FILE_PART, @@ -507,7 +518,7 @@ public void singleComponentFailureDuringIdentify() throws Exception { collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_REQUEST_SENT); - addStep("Send a identification response from pillar1 with a IDENTIFICATION_NEGATIVE response code .", + addStep("Send an identification response from pillar1 with an IDENTIFICATION_NEGATIVE response code .", "No events should be generated."); IdentifyPillarsForGetFileResponse identificationResponse1 = messageFactory.createIdentifyPillarsForGetFileResponse( @@ -516,8 +527,8 @@ public void singleComponentFailureDuringIdentify() throws Exception { messageBus.sendMessage(identificationResponse1); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_FAILED); - addStep("Send a identification response from pillar2 with a IDENTIFICATION_POSITIVE response code .", - "A component COMPONENT_IDENTIFIED event shouæd be generated followed by a IDENTIFICATION_COMPLETE."); + addStep("Send an identification response from pillar2 with an IDENTIFICATION_POSITIVE response code .", + "A component COMPONENT_IDENTIFIED event should be generated followed by an IDENTIFICATION_COMPLETE."); IdentifyPillarsForGetFileResponse identificationResponse2 = messageFactory.createIdentifyPillarsForGetFileResponse( receivedIdentifyRequestMessage, PILLAR2_ID, pillar2DestinationId); messageBus.sendMessage(identificationResponse2); @@ -544,7 +555,7 @@ public void failureDuringPerform() throws Exception { "during the performing phase."); addStep("Request a getFile from the fastest pillar.", - "A IDENTIFY_REQUEST_SENT should be generate and a identification request should be sent."); + "A IDENTIFY_REQUEST_SENT should be generate and an identification request should be sent."); GetFileClient client = createGetFileClient(); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); client.getFileFromFastestPillar(collectionID, DEFAULT_FILE_ID, NO_FILE_PART, @@ -553,7 +564,7 @@ public void failureDuringPerform() throws Exception { IdentifyPillarsForGetFileRequest receivedIdentifyRequestMessage = collectionReceiver.waitForMessage(IdentifyPillarsForGetFileRequest.class); - addStep("Send a identification response from pillar1 and pillar2 with pillar1 the fastest.", + addStep("Send an identification response from pillar1 and pillar2 with pillar1 the fastest.", "Pillar1 should be selected and a GetFileRequest should be sent."); IdentifyPillarsForGetFileResponse identificationResponse1 = messageFactory.createIdentifyPillarsForGetFileResponse( receivedIdentifyRequestMessage, PILLAR1_ID, pillar1DestinationId); @@ -605,7 +616,7 @@ public void getFileFromOtherCollection() throws Exception { assertEquals(receivedIdentifyRequestMessage.getCollectionID(), otherCollection); addStep("Send an identification response from pillar2.", - "An COMPONENT_IDENTIFIED event should be generate folled by a IDENTIFICATION_COMPLETE and a " + + "An COMPONENT_IDENTIFIED event should be generate followed by an IDENTIFICATION_COMPLETE and a " + "REQUEST_SENT. A GetFileIdsFileRequest should be sent to pillar2"); messageBus.sendMessage(messageFactory.createIdentifyPillarsForGetFileResponse( receivedIdentifyRequestMessage, PILLAR2_ID, pillar2DestinationId)); @@ -632,7 +643,9 @@ public void getFileFromOtherCollection() throws Exception { * @return A new GetFileClient(Wrapper). */ private GetFileClient createGetFileClient() { - return new GetFileClientTestWrapper(new ConversationBasedGetFileClient( - messageBus, conversationMediator, settingsForCUT, settingsForTestClient.getComponentID()), testEventManager); + return new GetFileClientTestWrapper( + new ConversationBasedGetFileClient(messageBus, conversationMediator, settingsForCUT, + settingsForTestClient.getComponentID()), + testEventManager); } } diff --git a/bitrepository-client/src/test/java/org/bitrepository/access/getstatus/GetStatusClientComponentTest.java b/bitrepository-client/src/test/java/org/bitrepository/access/getstatus/GetStatusClientComponentTest.java index d7255c902..65154587b 100644 --- a/bitrepository-client/src/test/java/org/bitrepository/access/getstatus/GetStatusClientComponentTest.java +++ b/bitrepository-client/src/test/java/org/bitrepository/access/getstatus/GetStatusClientComponentTest.java @@ -40,7 +40,7 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.math.BigInteger; +import javax.xml.datatype.DatatypeFactory; import java.util.List; import static org.testng.Assert.assertEquals; @@ -50,20 +50,20 @@ public class GetStatusClientComponentTest extends DefaultFixtureClientTest { private TestGetStatusMessageFactory testMessageFactory; @BeforeMethod(alwaysRun=true) - public void beforeMethodSetup() throws Exception { + public void beforeMethodSetup() { testMessageFactory = new TestGetStatusMessageFactory(settingsForTestClient.getComponentID()); if (settingsForCUT.getRepositorySettings().getGetStatusSettings() == null) { settingsForCUT.getRepositorySettings().setGetStatusSettings(new GetStatusSettings()); } - List contributers = settingsForCUT.getRepositorySettings().getGetStatusSettings().getNonPillarContributorIDs(); - contributers.clear(); - contributers.add(PILLAR1_ID); - contributers.add(PILLAR2_ID); + List contributors = settingsForCUT.getRepositorySettings().getGetStatusSettings().getNonPillarContributorIDs(); + contributors.clear(); + contributors.add(PILLAR1_ID); + contributors.add(PILLAR2_ID); } @Test(groups = {"regressiontest"}) - public void verifyGetStatusClientFromFactory() throws Exception { + public void verifyGetStatusClientFromFactory() { Assert.assertTrue(AccessComponentFactory.getInstance().createGetStatusClient( settingsForCUT, securityManager, settingsForTestClient.getComponentID()) instanceof ConversationBasedGetStatusClient, @@ -74,11 +74,13 @@ public void verifyGetStatusClientFromFactory() throws Exception { @Test(groups = {"regressiontest"}) public void incompleteSetOfIdendifyResponses() throws Exception { addDescription("Verify that the GetStatus client works correct without receiving responses from all " + - "contributers."); - addStep("Configure 1 second timeout for identifying contributers. " + - "The default 2 contributers collection is used", ""); + "contributors."); + addStep("Configure 1 second timeout for identifying contributors. " + + "The default 2 contributors collection is used", ""); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(1000)); + DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(1000)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); GetStatusClient client = createGetStatusClient(); @@ -113,7 +115,7 @@ public void incompleteSetOfIdendifyResponses() throws Exception { @Test(groups = {"regressiontest"}) public void getAllStatuses() throws InterruptedException { - addDescription("Tests the simplest case of getting status for all contributers."); + addDescription("Tests the simplest case of getting status for all contributors."); addStep("Create a GetStatusClient.", ""); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); diff --git a/bitrepository-client/src/test/java/org/bitrepository/client/DefaultClientTest.java b/bitrepository-client/src/test/java/org/bitrepository/client/DefaultClientTest.java index 26a369955..077b319cf 100644 --- a/bitrepository-client/src/test/java/org/bitrepository/client/DefaultClientTest.java +++ b/bitrepository-client/src/test/java/org/bitrepository/client/DefaultClientTest.java @@ -27,8 +27,11 @@ import org.bitrepository.client.eventhandler.OperationEvent; import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType; import org.bitrepository.protocol.bus.MessageReceiver; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; import java.math.BigInteger; import static org.testng.Assert.assertEquals; @@ -40,6 +43,12 @@ */ public abstract class DefaultClientTest extends DefaultFixtureClientTest { protected final TestEventHandler testEventHandler = new TestEventHandler(testEventManager); + private DatatypeFactory datatypeFactory; + + @BeforeMethod(alwaysRun = true) + public void setUpFactory() throws DatatypeConfigurationException { + datatypeFactory = DatatypeFactory.newInstance(); + } @Test(groups = {"regressiontest"}) public void identificationNegativeTest() throws Exception { @@ -129,7 +138,8 @@ public void oneContributorNotRespondingTest() throws Exception { addDescription("Verify that the client works correct without receiving identification responses from all " + "contributors."); addFixture("Set the a identification timeout to 100 ms."); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(100)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(100)); addStep("Start the operation.", "A IDENTIFY_REQUEST_SENT should be generate and a identification request should be sent."); @@ -170,7 +180,8 @@ public void noContributorsRespondingTest() throws Exception { "More concrete this means that the occurrence of a identification timeout should be handled correctly"); addStep("Set a 100 ms timeout for identifying contributors.", ""); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(100)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(100)); addStep("Start the operation.", "A IDENTIFY_REQUEST_SENT event should be generated."); startOperation(testEventHandler); @@ -189,7 +200,8 @@ public void operationTimeoutTest() throws Exception { addDescription("Tests the the client handles lack of final responses gracefully."); addStep("Set a 100 ms operation timeout.", ""); - settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeout(BigInteger.valueOf(100)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setOperationTimeoutDuration(datatypeFactory.newDuration(100)); addStep("Start the operation", "A IDENTIFY_REQUEST_SENT event should be received."); @@ -222,7 +234,8 @@ public void collectionIDIncludedInEventsTest() throws Exception { addDescription("Tests the the client provides collectionID in events."); addStep("Set a 0.5 second operation timeout.", ""); - settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeout(BigInteger.valueOf(500)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setOperationTimeoutDuration(datatypeFactory.newDuration(500)); addStep("Start the operation", "A IDENTIFY_REQUEST_SENT event should be received."); startOperation(testEventHandler); diff --git a/bitrepository-client/src/test/java/org/bitrepository/modify/deletefile/DeleteFileClientComponentTest.java b/bitrepository-client/src/test/java/org/bitrepository/modify/deletefile/DeleteFileClientComponentTest.java index 3819aae98..6e7a2d42d 100644 --- a/bitrepository-client/src/test/java/org/bitrepository/modify/deletefile/DeleteFileClientComponentTest.java +++ b/bitrepository-client/src/test/java/org/bitrepository/modify/deletefile/DeleteFileClientComponentTest.java @@ -45,15 +45,17 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.math.BigInteger; +import javax.xml.datatype.DatatypeFactory; import java.nio.charset.StandardCharsets; public class DeleteFileClientComponentTest extends DefaultFixtureClientTest { private TestDeleteFileMessageFactory messageFactory; + private DatatypeFactory datatypeFactory; @BeforeMethod(alwaysRun=true) public void initialise() throws Exception { messageFactory = new TestDeleteFileMessageFactory(collectionID); + datatypeFactory = DatatypeFactory.newInstance(); } @Test(groups={"regressiontest"}) @@ -94,8 +96,7 @@ public void deleteClientTester() throws Exception { testEventHandler, null); - IdentifyPillarsForDeleteFileRequest receivedIdentifyRequestMessage = null; - receivedIdentifyRequestMessage = collectionReceiver.waitForMessage( + IdentifyPillarsForDeleteFileRequest receivedIdentifyRequestMessage = collectionReceiver.waitForMessage( IdentifyPillarsForDeleteFileRequest.class); Assert.assertEquals(receivedIdentifyRequestMessage.getCollectionID(), collectionID); Assert.assertNotNull(receivedIdentifyRequestMessage.getCorrelationID()); @@ -193,7 +194,8 @@ public void deleteClientIdentificationTimeout() throws Exception { settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().clear(); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().add(PILLAR1_ID); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(1000L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(1000)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); DeleteFileClient deleteClient = createDeleteFileClient(); @@ -231,7 +233,8 @@ public void deleteClientOperationTimeout() throws Exception { settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().clear(); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().add(PILLAR1_ID); - settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeout(BigInteger.valueOf(100L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setOperationTimeoutDuration(datatypeFactory.newDuration(100)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); DeleteFileClient deleteClient = createDeleteFileClient(); diff --git a/bitrepository-client/src/test/java/org/bitrepository/modify/putfile/PutFileClientComponentTest.java b/bitrepository-client/src/test/java/org/bitrepository/modify/putfile/PutFileClientComponentTest.java index 0335e6a1f..ea2dcd7b0 100644 --- a/bitrepository-client/src/test/java/org/bitrepository/modify/putfile/PutFileClientComponentTest.java +++ b/bitrepository-client/src/test/java/org/bitrepository/modify/putfile/PutFileClientComponentTest.java @@ -44,6 +44,7 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import javax.xml.datatype.DatatypeFactory; import java.math.BigInteger; import java.util.concurrent.TimeUnit; @@ -51,12 +52,13 @@ public class PutFileClientComponentTest extends DefaultFixtureClientTest { private TestPutFileMessageFactory messageFactory; + private DatatypeFactory datatypeFactory; @BeforeMethod(alwaysRun=true) public void initialise() throws Exception { messageFactory = new TestPutFileMessageFactory(settingsForTestClient.getComponentID()); - -} + datatypeFactory = DatatypeFactory.newInstance(); + } @Test(groups={"regressiontest"}) public void verifyPutClientFromFactory() { @@ -143,12 +145,13 @@ public void noPillarsResponding() throws Exception { addDescription("Tests the handling of missing identification responses from all pillar"); addFixture("Sets the identification timeout to 100 ms."); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(100L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(100)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); PutFileClient putClient = createPutFileClient(); addStep("Request the putting of a file through the PutClient", - "A identification request should be dispatched."); + "An identification request should be dispatched."); putClient.putFile(collectionID, httpServerConfiguration.getURL(DEFAULT_FILE_ID), DEFAULT_FILE_ID, 0, null, null, testEventHandler, null); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_REQUEST_SENT); @@ -170,7 +173,8 @@ public void onePillarRespondingWithPartialPutAllowed() throws Exception { "when partial put are allowed"); addFixture("Sets the identification timeout to 100 ms and allow partial puts."); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(100L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(100)); settingsForCUT.getReferenceSettings().getPutFileSettings().setPartialPutsAllow(true); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); PutFileClient putClient = createPutFileClient(); @@ -191,7 +195,7 @@ public void onePillarRespondingWithPartialPutAllowed() throws Exception { assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_IDENTIFIED); addStep("Await the timeout.", "An IDENTIFY_TIMEOUT events, a COMPONENT_FAILED " + - "event for the non-responding pillar and a IDENTIFICATION_COMPLETE event should be generated."); + "event for the non-responding pillar and an IDENTIFICATION_COMPLETE event should be generated."); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFY_TIMEOUT); Assert.assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_FAILED); assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.IDENTIFICATION_COMPLETE); @@ -216,7 +220,8 @@ public void onePillarRespondingWithPartialPutDisallowed() throws Exception { "when partial put are allowed"); addFixture("Sets the identification timeout to 100 ms and disallow partial puts."); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(100L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(100)); settingsForCUT.getReferenceSettings().getPutFileSettings().setPartialPutsAllow(false); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); PutFileClient putClient = createPutFileClient(); @@ -252,7 +257,8 @@ public void putClientOperationTimeout() throws Exception { "Should be OK."); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().clear(); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().add(PILLAR1_ID); - settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeout(BigInteger.valueOf(100L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setOperationTimeoutDuration(datatypeFactory.newDuration(100)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); PutFileClient putClient = createPutFileClient(); @@ -531,7 +537,7 @@ public void saltedReturnChecksumsWithChecksumPillar() throws Exception { assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_IDENTIFIED); addStep("Send an normal identification response from pillar2.", - "An COMPONENT_IDENTIFIED event should be generate followed by a IDENTIFICATION_COMPLETE and a " + + "An COMPONENT_IDENTIFIED event should be generate followed by an IDENTIFICATION_COMPLETE and a " + "REQUEST_SENT. \nRequests for put files should be received, the one for the checksum pillar" + "without a request for a return checksum, and the request to the normal pillar" + "should specify that a salted checksum should be returned."); @@ -582,7 +588,7 @@ public void defaultReturnChecksumsWithChecksumPillar() throws Exception { assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_IDENTIFIED); addStep("Send an normal identification response from pillar2.", - "An COMPONENT_IDENTIFIED event should be generate followed by a IDENTIFICATION_COMPLETE and a " + + "An COMPONENT_IDENTIFIED event should be generate followed by an IDENTIFICATION_COMPLETE and a " + "REQUEST_SENT. \nRequests for put files should be received, both requesting a return checksum " + "of the default type a request for a return checksum, and the request to the normal pillar" + "should specify that a salted checksum should be returned."); @@ -631,7 +637,7 @@ public void noReturnChecksumsWithChecksumPillar() throws Exception { assertEquals(testEventHandler.waitForEvent().getEventType(), OperationEventType.COMPONENT_IDENTIFIED); addStep("Send an normal identification response from pillar2.", - "An COMPONENT_IDENTIFIED event should be generate followed by a IDENTIFICATION_COMPLETE and a " + + "An COMPONENT_IDENTIFIED event should be generate followed by an IDENTIFICATION_COMPLETE and a " + "REQUEST_SENT. \nRequests for put files should be received, neither requesting a return " + "checksum."); IdentifyPillarsForPutFileResponse identifyResponse2 = messageFactory.createIdentifyPillarsForPutFileResponse( @@ -790,8 +796,8 @@ public void putToOtherCollection() throws Exception { assertEquals(receivedIdentifyRequestMessage.getCollectionID(), otherCollection); addStep("Send an identification response from pillar2.", - "An COMPONENT_IDENTIFIED event should be generate folled by a IDENTIFICATION_COMPLETE and a " + - "REQUEST_SENT. A PutFileRequest should be sent to pillar2"); + "An COMPONENT_IDENTIFIED event should be generated followed by an IDENTIFICATION_COMPLETE" + + " and a REQUEST_SENT. A PutFileRequest should be sent to pillar2"); IdentifyPillarsForPutFileResponse identifyResponse = messageFactory.createIdentifyPillarsForPutFileResponse( receivedIdentifyRequestMessage, PILLAR2_ID, pillar2DestinationId); messageBus.sendMessage(identifyResponse); diff --git a/bitrepository-client/src/test/java/org/bitrepository/modify/replacefile/ReplaceFileClientComponentTest.java b/bitrepository-client/src/test/java/org/bitrepository/modify/replacefile/ReplaceFileClientComponentTest.java index a8567111b..917840ae9 100644 --- a/bitrepository-client/src/test/java/org/bitrepository/modify/replacefile/ReplaceFileClientComponentTest.java +++ b/bitrepository-client/src/test/java/org/bitrepository/modify/replacefile/ReplaceFileClientComponentTest.java @@ -45,7 +45,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.math.BigInteger; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -54,13 +55,15 @@ public class ReplaceFileClientComponentTest extends DefaultFixtureClientTest { private ChecksumDataForFileTYPE DEFAULT_OLD_CHECKSUM_DATA; private ChecksumDataForFileTYPE DEFAULT_NEW_CHECKSUM_DATA; private TestReplaceFileMessageFactory messageFactory; + private DatatypeFactory datatypeFactory; @BeforeMethod(alwaysRun = true) - public void initialise() throws Exception { + public void initialise() throws DatatypeConfigurationException { messageFactory = new TestReplaceFileMessageFactory(settingsForTestClient.getComponentID()); DEFAULT_CHECKSUM_SPEC = ChecksumUtils.getDefault(settingsForCUT); DEFAULT_OLD_CHECKSUM_DATA = createChecksumData("123checksum321"); DEFAULT_NEW_CHECKSUM_DATA = createChecksumData("123checksum321"); + datatypeFactory = DatatypeFactory.newInstance(); } @Test(groups = {"regressiontest"}) @@ -156,7 +159,8 @@ public void replaceClientIdentificationTimeout() throws Exception { "Should be OK."); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().clear(); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().add(PILLAR1_ID); - settingsForCUT.getRepositorySettings().getClientSettings().setIdentificationTimeout(BigInteger.valueOf(100L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setIdentificationTimeoutDuration(datatypeFactory.newDuration(100)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); ReplaceFileClient replaceClient = createReplaceFileClient(); ChecksumSpecTYPE checksumRequest = new ChecksumSpecTYPE(); @@ -187,7 +191,8 @@ public void replaceClientOperationTimeout() throws Exception { "Should be OK."); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().clear(); settingsForCUT.getRepositorySettings().getCollections().getCollection().get(0).getPillarIDs().getPillarID().add(PILLAR1_ID); - settingsForCUT.getRepositorySettings().getClientSettings().setOperationTimeout(BigInteger.valueOf(100L)); + settingsForCUT.getRepositorySettings().getClientSettings() + .setOperationTimeoutDuration(datatypeFactory.newDuration(100)); TestEventHandler testEventHandler = new TestEventHandler(testEventManager); ReplaceFileClient replaceClient = createReplaceFileClient(); diff --git a/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java b/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java index 6bb5ac9bc..00c2be721 100644 --- a/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java +++ b/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java @@ -30,6 +30,11 @@ import org.bitrepository.settings.repositorysettings.Permission; import org.bitrepository.settings.repositorysettings.RepositorySettings; +import javax.xml.datatype.DatatypeConstants; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.List; /** @@ -39,6 +44,8 @@ * Settings objects. */ public class Settings { + public static final BigInteger MILLIS_PER_SECOND = BigInteger.valueOf(Duration.ofSeconds(1).toMillis()); + protected final String componentID; protected final String receiverDestinationID; protected final ReferenceSettings referenceSettings; @@ -97,13 +104,77 @@ public List getPermissions() { } /** - * Wraps the {@link org.bitrepository.settings.repositorysettings.ClientSettings#getIdentificationTimeout()} method. + * Wraps the {@link org.bitrepository.settings.repositorysettings.ClientSettings#getIdentificationTimeout()} + * and {@link ClientSettings#getIdentificationTimeoutDuration()} ()} methods, preferring to use the latter. * * @return the timeout - * @see org.bitrepository.settings.repositorysettings.ClientSettings#getIdentificationTimeout() + * @see ClientSettings#getIdentificationTimeoutDuration() */ - public long getIdentificationTimeout() { - return getRepositorySettings().getClientSettings().getIdentificationTimeout().longValue(); + public Duration getIdentificationTimeout() { + // TODO Ole V. Once the old IdentificationTimeout settings in milliseconds is done away with, + // TODO the following code gets simpler + javax.xml.datatype.Duration xmlDuration = + getRepositorySettings().getClientSettings().getIdentificationTimeoutDuration(); + BigInteger identificationTimeoutMillis = + getRepositorySettings().getClientSettings().getIdentificationTimeout(); + return getDurationFromXmlDurationOrMillis(xmlDuration, identificationTimeoutMillis); + } + + public Duration getOperationTimeout() { + javax.xml.datatype.Duration xmlDuration = + getRepositorySettings().getClientSettings().getOperationTimeoutDuration(); + BigInteger operationTimeoutMillis = + getRepositorySettings().getClientSettings().getOperationTimeout(); + return getDurationFromXmlDurationOrMillis(xmlDuration, operationTimeoutMillis); + } + + static Duration getDurationFromXmlDurationOrMillis( + javax.xml.datatype.Duration xmlDuration, BigInteger millis) { + // Prefer the XML Duration + if (xmlDuration != null) { + validateNonNegative(xmlDuration); + return xmlDurationToDuration(xmlDuration); + } + BigInteger[] secondsAndMillis = millis.divideAndRemainder(MILLIS_PER_SECOND); + return Duration.ofSeconds(secondsAndMillis[0].longValueExact()) + .plusMillis(secondsAndMillis[1].intValueExact()); + } + + public static void validateNonNegative(javax.xml.datatype.Duration xmlDuration) { + if (xmlDuration.getSign() < 0) { + throw new IllegalArgumentException("Unexpected negative duration: " + xmlDuration); + } + } + + /** + * Converts a javax.xml.datatype.Duration to a java.time.Duration using estimated values for days, months and years. + */ + public static Duration xmlDurationToDuration(javax.xml.datatype.Duration xmlDuration) { + return unitsToDuration(xmlDuration.getField(DatatypeConstants.YEARS), ChronoUnit.YEARS) + .plus(unitsToDuration(xmlDuration.getField(DatatypeConstants.MONTHS), ChronoUnit.MONTHS)) + .plus(unitsToDuration(xmlDuration.getField(DatatypeConstants.DAYS), ChronoUnit.DAYS)) + .plus(unitsToDuration(xmlDuration.getField(DatatypeConstants.HOURS), ChronoUnit.HOURS)) + .plus(unitsToDuration(xmlDuration.getField(DatatypeConstants.MINUTES), ChronoUnit.MINUTES)) + .plus(secondsToDuration(xmlDuration.getField(DatatypeConstants.SECONDS))); + } + + /** @param count a BigInteger or null */ + private static Duration unitsToDuration(Number count, ChronoUnit unit) { + if (count == null) { + return Duration.ZERO; + } + return unit.getDuration().multipliedBy(((BigInteger) count).longValueExact()); + } + + /** @param secondsValue a BigDecimal denoting the number of seconds with fraction or null */ + private static Duration secondsToDuration(Number secondsValue) { + if (secondsValue == null) { + return Duration.ZERO; + } + BigDecimal secondsBigDecimal = (BigDecimal) secondsValue; + long wholeSeconds = secondsBigDecimal.toBigInteger().longValueExact(); + int nanos = secondsBigDecimal.subtract(BigDecimal.valueOf(wholeSeconds)).scaleByPowerOfTen(9).intValueExact(); + return Duration.ofSeconds(wholeSeconds, nanos); } /** diff --git a/bitrepository-core/src/main/java/org/bitrepository/common/utils/CountAndTimeUnit.java b/bitrepository-core/src/main/java/org/bitrepository/common/utils/CountAndTimeUnit.java new file mode 100644 index 000000000..44dd707e3 --- /dev/null +++ b/bitrepository-core/src/main/java/org/bitrepository/common/utils/CountAndTimeUnit.java @@ -0,0 +1,35 @@ +package org.bitrepository.common.utils; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class CountAndTimeUnit { + private final long count; + private final TimeUnit unit; + + public CountAndTimeUnit(long count, TimeUnit unit) { + this.count = count; + this.unit = Objects.requireNonNull(unit, "unit"); + } + + public long getCount() { + return count; + } + + public TimeUnit getUnit() { + return unit; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CountAndTimeUnit that = (CountAndTimeUnit) o; + return count == that.count && unit == that.unit; + } + + @Override + public int hashCode() { + return Objects.hash(count, unit); + } +} diff --git a/bitrepository-core/src/main/java/org/bitrepository/common/utils/TimeUtils.java b/bitrepository-core/src/main/java/org/bitrepository/common/utils/TimeUtils.java index feccec24f..28124ad4d 100644 --- a/bitrepository-core/src/main/java/org/bitrepository/common/utils/TimeUtils.java +++ b/bitrepository-core/src/main/java/org/bitrepository/common/utils/TimeUtils.java @@ -24,8 +24,10 @@ import javax.xml.datatype.XMLGregorianCalendar; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.concurrent.TimeUnit; /** * Util class to handle the presentation of time in a human-readable form @@ -123,6 +125,47 @@ public static String millisecondsToHuman(long ms) { return sb.toString(); } + /** + * @throws ArithmeticException if dur is negative by more than Long.MAX_VALUE seconds + */ + public static String durationToHuman(Duration dur) { + if (dur.isZero()) { + return "0 ms"; + } + + List parts = new ArrayList<>(5); + + if (dur.isNegative()) { + parts.add("minus"); + dur = dur.negated(); + } + + if (dur.toDays() > 0) { + parts.add("" + dur.toDays() + "d"); + } + if (dur.toHoursPart() > 0) { + parts.add("" + dur.toHoursPart() + "h"); + } + if (dur.toMinutesPart() > 0) { + parts.add("" + dur.toMinutesPart() + "m"); + } + if (dur.toSecondsPart() > 0) { + parts.add("" + dur.toSecondsPart() + "s"); + } + if (dur.toNanosPart() > 0) { + // If the fraction of second is a whole number of millis, print as such; otherwise print only as nanos + Duration fraction = Duration.ofNanos(dur.getNano()); + Duration remainderAfterMillis = fraction.minusMillis(fraction.toMillisPart()); + if (remainderAfterMillis.isZero()) { + parts.add("" + fraction.toMillisPart() + " ms"); + } else { + parts.add("" + fraction.toNanosPart() + " ns"); + } + } + + return String.join(" ", parts); + } + public static String shortDate(Date date) { return formatter.format(date); } @@ -145,4 +188,32 @@ public static Date getMaxDate(Date currentMax, Date itemDate) { return currentMax; } } + + /** + * + * @param duration a non-negative duration + * @return the duration converted to a long in either SECONDS, MILLISECONDS, MICROSECONDS or NANOSECONDS + * maintaining the best possible precision and truncated if necessary. + * @throws IllegalArgumentException if duration is negative + */ + public static CountAndTimeUnit durationToCountAndTimeUnit(Duration duration) { + if (duration.isNegative()) { + throw new IllegalArgumentException("duration must be 0 or positive, was " + duration); + } + + if (duration.compareTo(Duration.ofNanos(Long.MAX_VALUE)) <= 0) { // fits in nanos + return new CountAndTimeUnit(duration.toNanos(), TimeUnit.NANOSECONDS); + } + if (duration.compareTo(Duration.of(Long.MAX_VALUE, ChronoUnit.MICROS)) <= 0) { // fits in micros + return new CountAndTimeUnit(duration.dividedBy(ChronoUnit.MICROS.getDuration()), TimeUnit.MICROSECONDS); + } + if (duration.compareTo(Duration.ofMillis(Long.MAX_VALUE)) <= 0) { // fits in millis + return new CountAndTimeUnit(duration.toMillis(), TimeUnit.MILLISECONDS); + } + if (duration.compareTo(Duration.ofSeconds(Long.MAX_VALUE)) <= 0) { // fits in seconds + return new CountAndTimeUnit(duration.toSeconds(), TimeUnit.SECONDS); + } + return new CountAndTimeUnit(duration.toMinutes(), TimeUnit.MINUTES); + } + } diff --git a/bitrepository-core/src/test/java/org/bitrepository/common/settings/SettingsTest.java b/bitrepository-core/src/test/java/org/bitrepository/common/settings/SettingsTest.java new file mode 100644 index 000000000..97d06829c --- /dev/null +++ b/bitrepository-core/src/test/java/org/bitrepository/common/settings/SettingsTest.java @@ -0,0 +1,113 @@ +package org.bitrepository.common.settings; + +import org.jaccept.structure.ExtendedTestCase; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import java.math.BigInteger; +import java.time.Duration; + +public class SettingsTest extends ExtendedTestCase { + + private DatatypeFactory factory; + + @BeforeMethod(alwaysRun = true) + public void setUpFactory() throws DatatypeConfigurationException { + factory = DatatypeFactory.newInstance(); + } + + @Test(groups = {"regressiontest"}, expectedExceptions = NullPointerException.class) + public void getDurationFromXmlDurationOrMillisRequiresOneNonNullArg() { + addDescription("Tests that getDurationFromXmlDurationOrMillis() fails when given two nulls"); + addStep("null and null", "NPE"); + + Settings.getDurationFromXmlDurationOrMillis(null, null); + } + + + @Test(groups = {"regressiontest"}) + public void testGetDurationFromXmlDurationOrMillis() { + addDescription("Tests conversions and selection by getDurationFromXmlDurationOrMillis()"); + + addStep("null and some milliseconds", "Duration of millis"); + Assert.assertEquals(Settings.getDurationFromXmlDurationOrMillis(null, BigInteger.valueOf(54321)), + Duration.ofMillis(54321)); + + addStep("XML duration and null", "XML duration converted"); + Assert.assertEquals( + Settings.getDurationFromXmlDurationOrMillis( + factory.newDuration("PT7M"), null), + Duration.ofMinutes(7)); + + addStep("Conflicting XML duration and millis", "XML duration should be preferred"); + Assert.assertEquals( + Settings.getDurationFromXmlDurationOrMillis( + factory.newDuration("PT2M"), BigInteger.valueOf(13)), + Duration.ofMinutes(2)); + } + + @Test(groups = {"regressiontest"}, expectedExceptions = IllegalArgumentException.class) + public void negativeDurationIsRejected() { + Settings.validateNonNegative(factory.newDuration("-PT0.00001S")); + } + + @Test(groups = {"regressiontest"}) + public void testXmlDurationToDuration() { + addDescription("Tests xmlDurationToDuration in sunshine scenario cases"); + + addStep("Test correct and precise conversion", + "Hours, minutes and seconds are converted with full precision"); + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("PT3S")), + Duration.ofSeconds(3)); + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("PT3.3S")), + Duration.ofSeconds(3, 300_000_000)); + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("PT3.000000003S")), + Duration.ofSeconds(3, 3)); + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("PT3.123456789S")), + Duration.ofSeconds(3, 123_456_789)); + + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("PT4M")), + Duration.ofMinutes(4)); + + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("PT5H")), + Duration.ofHours(5)); + + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("PT6H7M8.9S")), + Duration.ofHours(6).plusMinutes(7).plusSeconds(8).plusMillis(900)); + + addStep("Test approximate conversion", + "Days, months and years are converted using estimated factors"); + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("P2D")), + Duration.ofDays(2)); + Assert.assertEquals(Settings.xmlDurationToDuration(factory.newDuration("P3DT4M")), + Duration.ofDays(3).plusMinutes(4)); + + // We require a month to be between 28 and 31 days exclusive + Duration minMonthLengthExclusive = Duration.ofDays(28); + Duration maxMonthLengthExclusive = Duration.ofDays(31); + Duration convertedMonth = Settings.xmlDurationToDuration(factory.newDuration("P1M")); + assertBetweenExclusive(convertedMonth, minMonthLengthExclusive, maxMonthLengthExclusive); + + // Two years is between 730 and 731 days + Duration minTwoYearsLengthExclusive = Duration.ofDays(2 * 365); + Duration maxTwoYearsLengthExclusive = Duration.ofDays(2 * 365 + 1); + Duration convertedTwoYears = Settings.xmlDurationToDuration(factory.newDuration("P2Y")); + assertBetweenExclusive(convertedTwoYears, minTwoYearsLengthExclusive, maxTwoYearsLengthExclusive); + } + + private static > void assertBetweenExclusive(T actual, T minExclusive, T maxExclusive) { + Assert.assertTrue(actual.compareTo(minExclusive) > 0); + Assert.assertTrue(actual.compareTo(maxExclusive) < 0); + } + + @Test(groups = {"regressiontest"}, expectedExceptions = ArithmeticException.class) + public void tooManyDecimalsAreRejected() { + addDescription("Tests that xmlDurationToDuration() rejects more than 9 decimals on seconds"); + addStep("Duration with 10 decimals, PT2.0123456789S", "ArithmeticException"); + Settings.xmlDurationToDuration(factory.newDuration("PT2.0123456789S")); + } + +} diff --git a/bitrepository-core/src/test/java/org/bitrepository/common/utils/TimeUtilsTest.java b/bitrepository-core/src/test/java/org/bitrepository/common/utils/TimeUtilsTest.java index 8bc2186f7..1d878cc6c 100644 --- a/bitrepository-core/src/test/java/org/bitrepository/common/utils/TimeUtilsTest.java +++ b/bitrepository-core/src/test/java/org/bitrepository/common/utils/TimeUtilsTest.java @@ -27,8 +27,11 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.Locale; +import java.util.concurrent.TimeUnit; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -78,9 +81,31 @@ public void zeroIntervalTest() throws Exception { assertEquals(zeroTimeString, " 0 ms"); } + @Test(groups = {"regressiontest"}) + public void durationsPrintHumanly() { + addDescription("Tests durationToHuman()"); + + assertTrue(TimeUtils.durationToHuman(Duration.ZERO).contains("0"), + "Zero duration should contain a 0 digit"); + + assertEquals(TimeUtils.durationToHuman(Duration.ofDays(2)), "2d"); + assertEquals(TimeUtils.durationToHuman(Duration.ofHours(3)), "3h"); + assertEquals(TimeUtils.durationToHuman(Duration.ofMinutes(5)), "5m"); + assertEquals(TimeUtils.durationToHuman(Duration.ofSeconds(7)), "7s"); + assertEquals(TimeUtils.durationToHuman(Duration.ofMillis(11)), "11 ms"); + assertEquals(TimeUtils.durationToHuman(Duration.ofNanos(13)), "13 ns"); + // When there are nanoseconds, don't print millis + assertEquals(TimeUtils.durationToHuman(Duration.ofNanos(999_999_937)), "999999937 ns"); + + assertEquals(TimeUtils.durationToHuman(Duration.ofDays(-2)), "minus 2d"); + assertEquals(TimeUtils.durationToHuman(Duration.ofNanos(-13)), "minus 13 ns"); + + Duration allUnits = Duration.parse("P3DT5H7M11.013000017S"); + assertEquals(TimeUtils.durationToHuman(allUnits), "3d 5h 7m 11s 13000017 ns"); + } /* - * The test only ensures that the output format is fixed. Which timezone the the date is + * The test only ensures that the output format is fixed. Which timezone the date is * formatted to depends on the default/system timezone. At some time the use of the old java Date * api should be discontinued and the new Java Time api used instead. */ @@ -89,6 +114,42 @@ public void shortDateTest() { DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm", Locale.ROOT); Date date = new Date(1360069129256L); String shortDateString = TimeUtils.shortDate(date); - Assert.assertEquals(shortDateString, formatter.format(date)); + Assert.assertEquals(shortDateString, formatter.format(date)); + } + + @Test(groups = {"regressiontest"}) + public void rejectsNegativeDuration() { + Assert.assertThrows(IllegalArgumentException.class, + () -> TimeUtils.durationToCountAndTimeUnit(Duration.ofSeconds(Long.MIN_VALUE))); + Assert.assertThrows(IllegalArgumentException.class, + () -> TimeUtils.durationToCountAndTimeUnit(Duration.ofNanos(-1))); } + + @Test(groups = {"regressiontest"}) + public void convertsDurationToCountAndTimeUnit() { + CountAndTimeUnit expectedZero = TimeUtils.durationToCountAndTimeUnit(Duration.ZERO); + Assert.assertEquals(expectedZero.getCount(), 0); + Assert.assertNotNull(expectedZero.getUnit()); + + Assert.assertEquals(TimeUtils.durationToCountAndTimeUnit(Duration.ofNanos(1)), + new CountAndTimeUnit(1, TimeUnit.NANOSECONDS)); + Assert.assertEquals(TimeUtils.durationToCountAndTimeUnit(Duration.ofNanos(Long.MAX_VALUE)), + new CountAndTimeUnit(Long.MAX_VALUE, TimeUnit.NANOSECONDS)); + Assert.assertEquals( + TimeUtils.durationToCountAndTimeUnit(Duration.of(Long.MAX_VALUE / 1000 + 1, ChronoUnit.MICROS)), + new CountAndTimeUnit(Long.MAX_VALUE / 1000 + 1, TimeUnit.MICROSECONDS)); + Assert.assertEquals(TimeUtils.durationToCountAndTimeUnit(Duration.of(Long.MAX_VALUE, ChronoUnit.MICROS)), + new CountAndTimeUnit(Long.MAX_VALUE, TimeUnit.MICROSECONDS)); + Assert.assertEquals( + TimeUtils.durationToCountAndTimeUnit(Duration.ofMillis(Long.MAX_VALUE / 1000 + 1)), + new CountAndTimeUnit(Long.MAX_VALUE / 1000 + 1, TimeUnit.MILLISECONDS)); + Assert.assertEquals(TimeUtils.durationToCountAndTimeUnit(Duration.ofMillis(Long.MAX_VALUE)), + new CountAndTimeUnit(Long.MAX_VALUE, TimeUnit.MILLISECONDS)); + Assert.assertEquals( + TimeUtils.durationToCountAndTimeUnit(Duration.ofSeconds(Long.MAX_VALUE / 1000 + 1)), + new CountAndTimeUnit(Long.MAX_VALUE / 1000 + 1, TimeUnit.SECONDS)); + Assert.assertEquals(TimeUtils.durationToCountAndTimeUnit(Duration.ofSeconds(Long.MAX_VALUE)), + new CountAndTimeUnit(Long.MAX_VALUE, TimeUnit.SECONDS)); + } + } diff --git a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityCollectorEventHandler.java b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityCollectorEventHandler.java index c54c69a98..b043daebc 100644 --- a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityCollectorEventHandler.java +++ b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityCollectorEventHandler.java @@ -27,11 +27,15 @@ import org.bitrepository.client.eventhandler.EventHandler; import org.bitrepository.client.eventhandler.OperationEvent; import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType; +import org.bitrepository.common.utils.CountAndTimeUnit; +import org.bitrepository.common.utils.TimeUtils; import org.bitrepository.integrityservice.cache.IntegrityModel; import org.bitrepository.integrityservice.workflow.IntegrityContributors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; +import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -44,18 +48,18 @@ public class IntegrityCollectorEventHandler implements EventHandler { private final Logger log = LoggerFactory.getLogger(getClass()); private final IntegrityModel store; - private final long timeout; + private final Duration timeout; private final BlockingQueue finalEventQueue = new LinkedBlockingQueue<>(); private final IntegrityContributors integrityContributors; /** * @param model The integrity model, where the results of GetChecksums or GetFileIDs are to be delivered. - * @param timeout The maximum amount of millisecond to wait for an result. + * @param timeout The maximum duration to wait for a result. * @param integrityContributors the integrity contributors */ - public IntegrityCollectorEventHandler(IntegrityModel model, long timeout, IntegrityContributors integrityContributors) { + public IntegrityCollectorEventHandler(IntegrityModel model, Duration timeout, IntegrityContributors integrityContributors) { this.store = model; - this.timeout = timeout; + this.timeout = Objects.requireNonNull(timeout, "timeout"); this.integrityContributors = integrityContributors; } @@ -80,14 +84,15 @@ public void handleEvent(OperationEvent event) { } /** - * Retrieves the final event when the operation finishes. The final event is awaited for 'timeout' amount - * of milliseconds. If no final events has occurred, then an InterruptedException is thrown. + * Retrieves the final event when the operation finishes. + * The final event is awaited for 'timeout'. If no final events has occurred, then null is returned. * - * @return The final event. - * @throws InterruptedException If it timeouts before the final event. + * @return The final event or null if no final events has occurred. + * @throws InterruptedException If interrupted while waiting. */ public OperationEvent getFinish() throws InterruptedException { - return finalEventQueue.poll(timeout, TimeUnit.MILLISECONDS); + CountAndTimeUnit pollTimeout = TimeUtils.durationToCountAndTimeUnit(timeout); + return finalEventQueue.poll(pollTimeout.getCount(), pollTimeout.getUnit()); } /** diff --git a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java index 3d97b852b..5e5378086 100644 --- a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java +++ b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/IntegrityEventCompleteAwaiter.java @@ -25,12 +25,14 @@ import org.bitrepository.client.eventhandler.OperationEvent; import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType; import org.bitrepository.common.settings.Settings; +import org.bitrepository.common.utils.CountAndTimeUnit; +import org.bitrepository.common.utils.TimeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; /** * EventHandler for awaiting an operation to be complete. @@ -41,7 +43,7 @@ public class IntegrityEventCompleteAwaiter implements EventHandler { /** * The amount of milliseconds before the results are required. */ - private final Long timeout; + private final Duration timeout; /** * The queue used to store the received operation events. @@ -54,8 +56,7 @@ public class IntegrityEventCompleteAwaiter implements EventHandler { * @param settings The settings. */ public IntegrityEventCompleteAwaiter(Settings settings) { - this.timeout = settings.getRepositorySettings().getClientSettings().getIdentificationTimeout().longValue() - + settings.getRepositorySettings().getClientSettings().getOperationTimeout().longValue(); + this.timeout = settings.getIdentificationTimeout().plus(settings.getOperationTimeout()); } @Override @@ -77,7 +78,8 @@ public void handleEvent(OperationEvent event) { */ public OperationEvent getFinish() { try { - return finalEventQueue.poll(timeout, TimeUnit.MILLISECONDS); + CountAndTimeUnit pollTimeout = TimeUtils.durationToCountAndTimeUnit(timeout); + return finalEventQueue.poll(pollTimeout.getCount(), pollTimeout.getUnit()); } catch (InterruptedException e) { throw new IllegalStateException("Interrupted while waiting for the final response.", e); } diff --git a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/SimpleChecksumEventHandler.java b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/SimpleChecksumEventHandler.java index dd00a3003..8baaa1041 100644 --- a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/SimpleChecksumEventHandler.java +++ b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/collector/SimpleChecksumEventHandler.java @@ -27,12 +27,16 @@ import org.bitrepository.client.eventhandler.EventHandler; import org.bitrepository.client.eventhandler.OperationEvent; import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType; +import org.bitrepository.common.utils.CountAndTimeUnit; +import org.bitrepository.common.utils.TimeUtils; import org.bitrepository.integrityservice.workflow.IntegrityContributors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -44,17 +48,17 @@ */ public class SimpleChecksumEventHandler implements EventHandler { private final Logger log = LoggerFactory.getLogger(getClass()); - private final long timeout; + private final Duration timeout; private final BlockingQueue finalEventQueue = new LinkedBlockingQueue<>(); private final IntegrityContributors integrityContributors; private final Map checksumResults = new HashMap<>(); /** - * @param timeout The maximum amount of millisecond to wait for a result. + * @param timeout The maximum duration to wait for a result. * @param integrityContributors the integrity contributors */ - public SimpleChecksumEventHandler(long timeout, IntegrityContributors integrityContributors) { - this.timeout = timeout; + public SimpleChecksumEventHandler(Duration timeout, IntegrityContributors integrityContributors) { + this.timeout = Objects.requireNonNull(timeout, "timeout"); this.integrityContributors = integrityContributors; } @@ -79,14 +83,15 @@ public void handleEvent(OperationEvent event) { } /** - * Retrieves the final event when the operation finishes. The final event is awaited for 'timeout' amount - * of milliseconds. If no final events has occurred, then an InterruptedException is thrown. + * Retrieves the final event when the operation finishes. The final event is awaited for 'timeout'. + * If no final events has occurred, then null is returned. * - * @return The final event. - * @throws InterruptedException If it timeouts before the final event. + * @return The final event or null if none has occurred. + * @throws InterruptedException If interrupted while waiting. */ public OperationEvent getFinish() throws InterruptedException { - return finalEventQueue.poll(timeout, TimeUnit.MILLISECONDS); + CountAndTimeUnit pollTimeout = TimeUtils.durationToCountAndTimeUnit(timeout); + return finalEventQueue.poll(pollTimeout.getCount(), pollTimeout.getUnit()); } /** diff --git a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/GetChecksumForFileStep.java b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/GetChecksumForFileStep.java index 6652b2090..087aacede 100644 --- a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/GetChecksumForFileStep.java +++ b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/GetChecksumForFileStep.java @@ -37,6 +37,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -49,7 +50,7 @@ public class GetChecksumForFileStep extends AbstractWorkFlowStep { private final IntegrityInformationCollector collector; private final ChecksumSpecTYPE checksumType; private final IntegrityAlerter alerter; - private final Long timeout; + private final Duration timeout; protected final String fileID; protected final String collectionID; private final IntegrityContributors integrityContributors; @@ -72,8 +73,7 @@ public GetChecksumForFileStep(IntegrityInformationCollector collector, Integrity this.collectionID = collectionID; this.fileID = fileID; this.integrityContributors = integrityContributors; - this.timeout = settings.getRepositorySettings().getClientSettings().getIdentificationTimeout().longValue() + - settings.getRepositorySettings().getClientSettings().getOperationTimeout().longValue(); + this.timeout = settings.getIdentificationTimeout().plus(settings.getOperationTimeout()); } @Override diff --git a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateChecksumsStep.java b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateChecksumsStep.java index a242e3806..073f30b33 100644 --- a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateChecksumsStep.java +++ b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateChecksumsStep.java @@ -38,6 +38,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -53,7 +54,7 @@ public abstract class UpdateChecksumsStep extends AbstractWorkFlowStep { protected final IntegrityModel store; private final ChecksumSpecTYPE checksumType; private final IntegrityAlerter alerter; - private final Long timeout; + private final Duration timeout; private final Integer maxNumberOfResultsPerConversation; protected final String collectionID; private boolean abortInCaseOfFailure = true; @@ -74,8 +75,7 @@ public UpdateChecksumsStep(IntegrityInformationCollector collector, IntegrityMod this.alerter = alerter; this.collectionID = collectionID; this.integrityContributors = integrityContributors; - this.timeout = settings.getRepositorySettings().getClientSettings().getIdentificationTimeout().longValue() + - settings.getRepositorySettings().getClientSettings().getOperationTimeout().longValue(); + this.timeout = settings.getIdentificationTimeout().plus(settings.getOperationTimeout()); this.maxNumberOfResultsPerConversation = SettingsUtils.getMaxClientPageSize(); if (settings.getReferenceSettings().getIntegrityServiceSettings().isSetAbortOnFailedContributor()) { abortInCaseOfFailure = settings.getReferenceSettings().getIntegrityServiceSettings().isAbortOnFailedContributor(); diff --git a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateFileIDsStep.java b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateFileIDsStep.java index d7cbc9989..8817669bb 100644 --- a/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateFileIDsStep.java +++ b/bitrepository-integrity-service/src/main/java/org/bitrepository/integrityservice/workflow/step/UpdateFileIDsStep.java @@ -38,6 +38,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -52,7 +53,7 @@ public abstract class UpdateFileIDsStep extends AbstractWorkFlowStep { private final IntegrityInformationCollector collector; protected final IntegrityModel store; private final IntegrityAlerter alerter; - private final Long timeout; + private final Duration timeout; private final Integer maxNumberOfResultsPerConversation; protected final String collectionID; private boolean abortInCaseOfFailure = true; @@ -71,8 +72,7 @@ public UpdateFileIDsStep(IntegrityInformationCollector collector, IntegrityModel this.alerter = alerter; this.collectionID = collectionID; this.integrityContributors = integrityContributors; - this.timeout = settings.getRepositorySettings().getClientSettings().getIdentificationTimeout().longValue() + - settings.getRepositorySettings().getClientSettings().getOperationTimeout().longValue(); + this.timeout = settings.getIdentificationTimeout().plus(settings.getOperationTimeout()); this.maxNumberOfResultsPerConversation = SettingsUtils.getMaxClientPageSize(); if (settings.getReferenceSettings().getIntegrityServiceSettings().isSetAbortOnFailedContributor()) { abortInCaseOfFailure = settings.getReferenceSettings().getIntegrityServiceSettings().isAbortOnFailedContributor(); From 9c2db0a1e59edcca3381b8eb7bf7298e8e5ee5b3 Mon Sep 17 00:00:00 2001 From: "Ole V. Villumsen" Date: Mon, 1 Aug 2022 10:14:44 +0200 Subject: [PATCH 3/8] Add word 'TODO' with recommendation for Java 18 for noticeability (after review) --- .../client/conversation/GeneralConversationState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java index 78bf7902d..90ec35c5f 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java +++ b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/GeneralConversationState.java @@ -74,7 +74,7 @@ protected GeneralConversationState(Collection expectedContributors) { public void start() { try { if (!responseStatus.getOutstandingComponents().isEmpty()) { - if (getTimeoutValue().compareTo(Duration.ZERO) > 0) { // From Java 18 use: getTimeoutValue().isPositive() + if (getTimeoutValue().compareTo(Duration.ZERO) > 0) { // TODO From Java 18 use: getTimeoutValue().isPositive() CountAndTimeUnit delay = TimeUtils.durationToCountAndTimeUnit(getTimeoutValue()); scheduledTimeout = timer.schedule(new TimeoutHandler(), delay.getCount(), delay.getUnit()); } From cb80f818a0cc4e5702b9dfa20ce01880174c61f2 Mon Sep 17 00:00:00 2001 From: "Ole V. Villumsen" Date: Mon, 1 Aug 2022 10:54:23 +0200 Subject: [PATCH 4/8] BITMAG-992 further JavaDoc polish (partly after review) --- .../mediator/CollectionBasedConversationMediator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java index 1baae5e1d..1e6bf73e3 100644 --- a/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java +++ b/bitrepository-client/src/main/java/org/bitrepository/client/conversation/mediator/CollectionBasedConversationMediator.java @@ -96,7 +96,7 @@ public void addConversation(Conversation conversation) { } /** - * Will try to fail a conversation gracefully. This entitles: + * Will try to fail a conversation gracefully. This consists of: *

      *
    • Removing the conversation from the list of conversations. *
    • Attempt to call the failConversation operation on the conversation. The call is made in a separate thread to @@ -136,7 +136,7 @@ public void onMessage(Message message, MessageContext messageContext) { } /** - * Will clean out obsolete conversations in each run. An obsolete conversation is a conversation which satisfies ony + * Will clean out obsolete conversations in each run. An obsolete conversation is a conversation which satisfies any * of the following criteria:
        *
      1. Returns true for the hasEnded() method. *
      2. Is older than the conversationTimeout limit allows. From 9a061adf07e97d1d20fa8b4b9ad586dcb75bd875 Mon Sep 17 00:00:00 2001 From: "Ole V. Villumsen" Date: Mon, 29 Aug 2022 10:41:12 +0200 Subject: [PATCH 5/8] BITMAG-992 Upgrade example and test repository settings to use human-readable settings --- .../bitrepository/common/settings/Settings.java | 1 - .../examples/settings/RepositorySettings.xml | 16 ++++++++++------ .../bitrepository-devel/RepositorySettings.xml | 4 ++-- .../quickstart/conf/RepositorySettings.xml | 4 ++-- .../src/test/conf/RepositorySettings.xml | 4 ++-- .../test/resources/conf/RepositorySettings.xml | 4 ++-- 6 files changed, 18 insertions(+), 15 deletions(-) diff --git a/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java b/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java index 00c2be721..0409d7bef 100644 --- a/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java +++ b/bitrepository-core/src/main/java/org/bitrepository/common/settings/Settings.java @@ -130,7 +130,6 @@ public Duration getOperationTimeout() { static Duration getDurationFromXmlDurationOrMillis( javax.xml.datatype.Duration xmlDuration, BigInteger millis) { - // Prefer the XML Duration if (xmlDuration != null) { validateNonNegative(xmlDuration); return xmlDurationToDuration(xmlDuration); diff --git a/bitrepository-core/src/main/resources/examples/settings/RepositorySettings.xml b/bitrepository-core/src/main/resources/examples/settings/RepositorySettings.xml index 995765cd6..86964728f 100644 --- a/bitrepository-core/src/main/resources/examples/settings/RepositorySettings.xml +++ b/bitrepository-core/src/main/resources/examples/settings/RepositorySettings.xml @@ -76,7 +76,7 @@ --> topic://dummy-repository-id topic://dummy-repository-id.alarms @@ -95,17 +95,21 @@ - 10000 + PT10S - 3600000 + PT1H process-classes 31 - 14-SNAPSHOT + 14 10.14.2.0 5.16.4 3.3.6