From 2bd8bc69a13f49e377c36009a5c84e87c150cc46 Mon Sep 17 00:00:00 2001 From: Peter Winckles Date: Sun, 8 Jan 2023 13:00:11 -0600 Subject: [PATCH] use atomic booleans to track closed state The booleans that track whether the repository has been closed should technically be atomic so that their visibility is guaranteed across threads. This is a minor bug here, because ocfl-java doesn't currently do much on close. --- .../ocfl/core/DefaultOcflRepository.java | 10 ++++++---- .../ocfl/core/storage/AbstractOcflStorage.java | 17 +++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/DefaultOcflRepository.java b/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/DefaultOcflRepository.java index 60f272af..e6c72cb4 100644 --- a/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/DefaultOcflRepository.java +++ b/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/DefaultOcflRepository.java @@ -76,6 +76,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -105,7 +106,7 @@ public class DefaultOcflRepository implements OcflRepository { private Clock clock; - private boolean closed = false; + private final AtomicBoolean closed = new AtomicBoolean(false); /** * @see OcflRepositoryBuilder @@ -550,8 +551,9 @@ public void importObject(Path objectPath, OcflOption... options) { public void close() { LOG.debug("Close OCFL repository"); - closed = true; - storage.close(); + if (closed.compareAndSet(false, true)) { + storage.close(); + } } /** @@ -875,7 +877,7 @@ protected OffsetDateTime now(VersionInfo versionInfo) { } protected void ensureOpen() { - if (closed) { + if (closed.get()) { throw new OcflStateException(DefaultOcflRepository.class.getName() + " is closed."); } } diff --git a/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/storage/AbstractOcflStorage.java b/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/storage/AbstractOcflStorage.java index e41dea5e..40753d3b 100644 --- a/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/storage/AbstractOcflStorage.java +++ b/ocfl-java-core/src/main/java/edu/wisc/library/ocfl/core/storage/AbstractOcflStorage.java @@ -30,17 +30,18 @@ import edu.wisc.library.ocfl.core.extension.ExtensionSupportEvaluator; import edu.wisc.library.ocfl.core.extension.OcflExtensionConfig; import edu.wisc.library.ocfl.core.inventory.InventoryMapper; +import java.util.concurrent.atomic.AtomicBoolean; /** * OcflStorage abstract implementation that handles managing the repository's state, initialized, open, close. */ public abstract class AbstractOcflStorage implements OcflStorage { + private final AtomicBoolean closed = new AtomicBoolean(false); + private final AtomicBoolean initialized = new AtomicBoolean(false); + protected InventoryMapper inventoryMapper; protected ExtensionSupportEvaluator supportEvaluator; - - private boolean closed = false; - private boolean initialized = false; private RepositoryConfig repositoryConfig; /** @@ -52,7 +53,7 @@ public synchronized RepositoryConfig initializeStorage( OcflExtensionConfig layoutConfig, InventoryMapper inventoryMapper, ExtensionSupportEvaluator supportEvaluator) { - if (this.initialized) { + if (this.initialized.get()) { return this.repositoryConfig; } @@ -60,7 +61,7 @@ public synchronized RepositoryConfig initializeStorage( this.supportEvaluator = Enforce.notNull(supportEvaluator, "supportEvaluator cannot be null"); this.repositoryConfig = doInitialize(ocflVersion, layoutConfig); - this.initialized = true; + this.initialized.set(true); return repositoryConfig; } @@ -69,7 +70,7 @@ public synchronized RepositoryConfig initializeStorage( */ @Override public void close() { - closed = true; + closed.set(true); } /** @@ -100,11 +101,11 @@ public void invalidateCache() { * Throws an exception if the repository has not been initialized or is closed */ protected void ensureOpen() { - if (closed) { + if (closed.get()) { throw new OcflStateException(this.getClass().getName() + " is closed."); } - if (!initialized) { + if (!initialized.get()) { throw new OcflStateException(this.getClass().getName() + " must be initialized before it can be used."); } }