Skip to content

Commit

Permalink
Polishing.
Browse files Browse the repository at this point in the history
Use Lock utility for easier lock handling.

Original Pull Request: #4431
See also: spring-projects/spring-data-commmons#2944
  • Loading branch information
mp911de authored and christophstrobl committed Oct 5, 2023
1 parent cc56a93 commit 661607a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;

import org.bson.Document;
Expand All @@ -50,6 +47,7 @@
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.util.Lock;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
Expand Down Expand Up @@ -192,20 +190,18 @@ default SessionScoped withSession(Supplier<ClientSession> sessionProvider) {

return new SessionScoped() {

private final Lock lock = new ReentrantLock();
private final Lock lock = Lock.of(new ReentrantLock());
private @Nullable ClientSession session;

@Override
public <T> T execute(SessionCallback<T> action, Consumer<ClientSession> onComplete) {

lock.lock();
try {
lock.executeWithoutResult(() -> {

if (session == null) {
session = sessionProvider.get();
}
} finally {
lock.unlock();
}
});

try {
return action.doInSession(MongoOperations.this.withSession(session));
Expand Down Expand Up @@ -950,8 +946,8 @@ default <T> List<T> findDistinct(Query query, String field, String collection, C
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify </a>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @return the converted object that was updated before it was updated or {@literal null}, if not found.
Expand All @@ -966,8 +962,8 @@ default <T> List<T> findDistinct(Query query, String field, String collection, C
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify </a>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @param collectionName the collection to query. Must not be {@literal null}.
Expand All @@ -984,8 +980,8 @@ default <T> List<T> findDistinct(Query query, String field, String collection, C
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* {@link FindAndModifyOptions} into account.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification.
* @param update the {@link UpdateDefinition} to apply on matching documents.
* @param options the {@link FindAndModifyOptions} holding additional information.
* @param entityClass the parametrized type.
Expand All @@ -1004,8 +1000,8 @@ default <T> List<T> findDistinct(Query query, String field, String collection, C
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* {@link FindAndModifyOptions} into account.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
Expand All @@ -1030,8 +1026,8 @@ <T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions o
* Options are defaulted to {@link FindAndReplaceOptions#empty()}. <br />
* <strong>NOTE:</strong> The replacement entity must not hold an {@literal id}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param replacement the replacement document. Must not be {@literal null}.
* @return the converted object that was updated or {@literal null}, if not found.
* @throws org.springframework.data.mapping.MappingException if the collection name cannot be
Expand All @@ -1051,8 +1047,8 @@ default <T> T findAndReplace(Query query, T replacement) {
* Options are defaulted to {@link FindAndReplaceOptions#empty()}. <br />
* <strong>NOTE:</strong> The replacement entity must not hold an {@literal id}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param replacement the replacement document. Must not be {@literal null}.
* @param collectionName the collection to query. Must not be {@literal null}.
* @return the converted object that was updated or {@literal null}, if not found.
Expand All @@ -1070,8 +1066,8 @@ default <T> T findAndReplace(Query query, T replacement, String collectionName)
* taking {@link FindAndReplaceOptions} into account.<br />
* <strong>NOTE:</strong> The replacement entity must not hold an {@literal id}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param replacement the replacement document. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @return the converted object that was updated or {@literal null}, if not found. Depending on the value of
Expand All @@ -1093,8 +1089,8 @@ default <T> T findAndReplace(Query query, T replacement, FindAndReplaceOptions o
* taking {@link FindAndReplaceOptions} into account.<br />
* <strong>NOTE:</strong> The replacement entity must not hold an {@literal id}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param replacement the replacement document. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @return the converted object that was updated or {@literal null}, if not found. Depending on the value of
Expand All @@ -1116,8 +1112,8 @@ default <T> T findAndReplace(Query query, T replacement, FindAndReplaceOptions o
* taking {@link FindAndReplaceOptions} into account.<br />
* <strong>NOTE:</strong> The replacement entity must not hold an {@literal id}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param replacement the replacement document. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @param entityType the parametrized type. Must not be {@literal null}.
Expand All @@ -1141,8 +1137,8 @@ default <T> T findAndReplace(Query query, T replacement, FindAndReplaceOptions o
* taking {@link FindAndReplaceOptions} into account.<br />
* <strong>NOTE:</strong> The replacement entity must not hold an {@literal id}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param replacement the replacement document. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @param entityType the type used for mapping the {@link Query} to domain type fields and deriving the collection
Expand Down Expand Up @@ -1171,8 +1167,8 @@ default <S, T> T findAndReplace(Query query, S replacement, FindAndReplaceOption
* taking {@link FindAndReplaceOptions} into account.<br />
* <strong>NOTE:</strong> The replacement entity must not hold an {@literal id}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an optional
* fields specification. Must not be {@literal null}.
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document and also an
* optional fields specification. Must not be {@literal null}.
* @param replacement the replacement document. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @param entityType the type used for mapping the {@link Query} to domain type fields. Must not be {@literal null}.
Expand Down Expand Up @@ -1680,7 +1676,8 @@ default long exactCount(Query query, String collectionName) {
* acknowledged} remove operation was successful or not.
*
* @param object must not be {@literal null}.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null} or empty.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null}
* or empty.
* @return the {@link DeleteResult} which lets you access the results of the previous delete.
*/
DeleteResult remove(Object object, String collectionName);
Expand All @@ -1704,7 +1701,8 @@ default long exactCount(Query query, String collectionName) {
*
* @param query the query document that specifies the criteria used to remove a document.
* @param entityClass class of the pojo to be operated on. Can be {@literal null}.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null} or empty.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null}
* or empty.
* @return the {@link DeleteResult} which lets you access the results of the previous delete.
* @throws IllegalArgumentException when {@literal query}, {@literal entityClass} or {@literal collectionName} is
* {@literal null}.
Expand All @@ -1718,7 +1716,8 @@ default long exactCount(Query query, String collectionName) {
* information. Use {@link #remove(Query, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to remove a document.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null} or empty.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null}
* or empty.
* @return the {@link DeleteResult} which lets you access the results of the previous delete.
* @throws IllegalArgumentException when {@literal query} or {@literal collectionName} is {@literal null}.
*/
Expand All @@ -1730,7 +1729,8 @@ default long exactCount(Query query, String collectionName) {
* information. Use {@link #findAllAndRemove(Query, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to find and remove documents.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null} or empty.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null}
* or empty.
* @return the {@link List} converted objects deleted by this operation.
* @since 1.5
*/
Expand All @@ -1755,7 +1755,8 @@ default long exactCount(Query query, String collectionName) {
*
* @param query the query document that specifies the criteria used to find and remove documents.
* @param entityClass class of the pojo to be operated on.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null} or empty.
* @param collectionName name of the collection where the documents will be removed from, must not be {@literal null}
* or empty.
* @return the {@link List} converted objects deleted by this operation.
* @since 1.5
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;
Expand All @@ -42,6 +41,8 @@
import org.springframework.data.mongodb.ClientSessionException;
import org.springframework.data.mongodb.LazyLoadingException;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.util.Lock;
import org.springframework.data.util.Lock.AcquiredLock;
import org.springframework.lang.Nullable;
import org.springframework.objenesis.SpringObjenesis;
import org.springframework.util.ReflectionUtils;
Expand Down Expand Up @@ -175,7 +176,9 @@ public static class LazyLoadingInterceptor
}
}

private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = Lock.of(rwLock.readLock());
private final Lock writeLock = Lock.of(rwLock.writeLock());

private final MongoPersistentProperty property;
private final DbRefResolverCallback callback;
Expand Down Expand Up @@ -347,8 +350,7 @@ private void readObject(ObjectInputStream in) throws IOException {
@Nullable
private Object resolve() {

lock.readLock().lock();
try {
try (AcquiredLock l = readLock.lock()) {
if (resolved) {

if (LOGGER.isTraceEnabled()) {
Expand All @@ -357,8 +359,6 @@ private Object resolve() {
}
return result;
}
} finally {
lock.readLock().unlock();
}

if (LOGGER.isTraceEnabled()) {
Expand All @@ -367,7 +367,7 @@ private Object resolve() {
}

try {
return executeWhileLocked(lock.writeLock(), () -> callback.resolve(property));
return writeLock.execute(() -> callback.resolve(property));
} catch (RuntimeException ex) {

DataAccessException translatedException = exceptionTranslator.translateExceptionIfPossible(ex);
Expand All @@ -381,15 +381,6 @@ private Object resolve() {
}
}

private static <T> T executeWhileLocked(Lock lock, Supplier<T> stuff) {

lock.lock();
try {
return stuff.get();
} finally {
lock.unlock();
}
}
}

}
Loading

0 comments on commit 661607a

Please sign in to comment.