DELTASPIKE-1120 refactoring to LockedStrategy
Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/96319066 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/96319066 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/96319066 Branch: refs/heads/master Commit: 9631906615f9c6b80675e960387dc465c453e595 Parents: 943cf54 Author: gpetracek <[email protected]> Authored: Tue Apr 12 00:33:12 2016 +0200 Committer: gpetracek <[email protected]> Committed: Tue Apr 12 01:02:12 2016 +0200 ---------------------------------------------------------------------- .../core/spi/lock/LockedStrategy.java | 25 ++++ .../core/impl/lock/DefaultLockedStrategy.java | 47 +++++++ .../deltaspike/core/impl/lock/LockSupplier.java | 26 ++++ .../core/impl/lock/LockSupplierStorage.java | 140 +++++++++++++++++++ .../core/impl/lock/LockedInterceptor.java | 134 +----------------- 5 files changed, 241 insertions(+), 131 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/96319066/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/lock/LockedStrategy.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/lock/LockedStrategy.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/lock/LockedStrategy.java new file mode 100644 index 0000000..bdfa0e1 --- /dev/null +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/lock/LockedStrategy.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.deltaspike.core.spi.lock; + +import org.apache.deltaspike.core.spi.InterceptorStrategy; + +public interface LockedStrategy extends InterceptorStrategy +{ +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/96319066/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/DefaultLockedStrategy.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/DefaultLockedStrategy.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/DefaultLockedStrategy.java new file mode 100644 index 0000000..37ee5de --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/DefaultLockedStrategy.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.deltaspike.core.impl.lock; + +import org.apache.deltaspike.core.spi.lock.LockedStrategy; + +import javax.enterprise.context.Dependent; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; +import java.util.concurrent.locks.Lock; + +@Dependent +public class DefaultLockedStrategy implements LockedStrategy +{ + @Inject + private LockSupplierStorage lockSupplierStorage; + + @Override + public Object execute(InvocationContext ic) throws Exception + { + final Lock lock = lockSupplierStorage.getLockSupplier(ic).get(); + try + { + return ic.proceed(); + } + finally + { + lock.unlock(); + } + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/96319066/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplier.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplier.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplier.java new file mode 100644 index 0000000..9a3b1bc --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplier.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.deltaspike.core.impl.lock; + +import java.util.concurrent.locks.Lock; + +interface LockSupplier +{ + Lock get(); +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/96319066/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplierStorage.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplierStorage.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplierStorage.java new file mode 100644 index 0000000..6a720c1 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockSupplierStorage.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.deltaspike.core.impl.lock; + +import org.apache.deltaspike.core.api.lock.Locked; +import org.apache.deltaspike.core.impl.util.AnnotatedMethods; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.spi.AnnotatedMethod; +import javax.enterprise.inject.spi.AnnotatedType; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; +import java.lang.reflect.Method; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import static org.apache.deltaspike.core.api.lock.Locked.Operation.READ; + +@ApplicationScoped +@Typed(LockSupplierStorage.class) +public class LockSupplierStorage implements Locked.LockFactory +{ + private final ConcurrentMap<String, ReadWriteLock> locks = new ConcurrentHashMap<String, ReadWriteLock>(); + + // read or write + private final ConcurrentMap<Method, LockSupplier> lockSuppliers = new ConcurrentHashMap<Method, LockSupplier>(); + + @Inject + private BeanManager beanManager; + + protected LockSupplier getLockSupplier(final InvocationContext ic) + { + final Method key = ic.getMethod(); + LockSupplier operation = lockSuppliers.get(key); + if (operation == null) + { + final Class declaringClass = key.getDeclaringClass(); + final AnnotatedType<Object> annotatedType = beanManager.createAnnotatedType(declaringClass); + final AnnotatedMethod<?> annotatedMethod = AnnotatedMethods.findMethod(annotatedType, key); + + Locked config = annotatedMethod.getAnnotation(Locked.class); + if (config == null) + { + config = annotatedType.getAnnotation(Locked.class); + } + final Locked.LockFactory factory = config.factory() != Locked.LockFactory.class ? + Locked.LockFactory.class.cast( + beanManager.getReference(beanManager.resolve( + beanManager.getBeans( + config.factory())), + Locked.LockFactory.class, null)) : this; + + final ReadWriteLock writeLock = factory.newLock(annotatedMethod, config.fair()); + final long timeout = config.timeoutUnit().toMillis(config.timeout()); + final Lock lock = config.operation() == READ ? writeLock.readLock() : writeLock.writeLock(); + + if (timeout > 0) + { + operation = new LockSupplier() + { + @Override + public Lock get() + { + try + { + if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) + { + throw new IllegalStateException("Can't lock for " + key + " in " + timeout + "ms"); + } + } + catch (final InterruptedException e) + { + Thread.interrupted(); + throw new IllegalStateException("Locking interrupted", e); + } + return lock; + } + }; + } + else + { + operation = new LockSupplier() + { + @Override + public Lock get() + { + lock.lock(); + return lock; + } + }; + } + + final LockSupplier existing = lockSuppliers.putIfAbsent(key, operation); + if (existing != null) + { + operation = existing; + } + } + return operation; + } + + @Override + public ReadWriteLock newLock(final AnnotatedMethod<?> method, final boolean fair) + { + final String name = method.getJavaMember().getDeclaringClass().getName(); + ReadWriteLock lock = locks.get(name); + if (lock == null) + { + lock = new ReentrantReadWriteLock(fair); + final ReadWriteLock existing = locks.putIfAbsent(name, lock); + if (existing != null) + { + lock = existing; + } + } + return lock; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/96319066/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockedInterceptor.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockedInterceptor.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockedInterceptor.java index aff1efc..d413f5f 100644 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockedInterceptor.java +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/lock/LockedInterceptor.java @@ -19,152 +19,24 @@ package org.apache.deltaspike.core.impl.lock; import org.apache.deltaspike.core.api.lock.Locked; -import org.apache.deltaspike.core.impl.util.AnnotatedMethods; +import org.apache.deltaspike.core.spi.lock.LockedStrategy; -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.inject.Typed; -import javax.enterprise.inject.spi.AnnotatedMethod; -import javax.enterprise.inject.spi.AnnotatedType; -import javax.enterprise.inject.spi.BeanManager; import javax.inject.Inject; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import static org.apache.deltaspike.core.api.lock.Locked.Operation.READ; @Locked @Interceptor public class LockedInterceptor implements Serializable { @Inject - private Locks locks; + private LockedStrategy lockedStrategy; @AroundInvoke public Object invoke(final InvocationContext ic) throws Exception { - final Lock l = locks.lockAcquirer(ic).get(); - try - { - return ic.proceed(); - } - finally - { - l.unlock(); - } - } - - @ApplicationScoped - @Typed(Locks.class) - static class Locks implements Locked.LockFactory - { - private final ConcurrentMap<String, ReadWriteLock> locks = new ConcurrentHashMap<String, ReadWriteLock>(); - - // read or write - private final ConcurrentMap<Method, LockSupplier> lockSuppliers = new ConcurrentHashMap<Method, LockSupplier>(); - - @Inject - private BeanManager beanManager; - - LockSupplier lockAcquirer(final InvocationContext ic) - { - final Method key = ic.getMethod(); - LockSupplier operation = lockSuppliers.get(key); - if (operation == null) - { - final Class declaringClass = key.getDeclaringClass(); - final AnnotatedType<Object> annotatedType = beanManager.createAnnotatedType(declaringClass); - final AnnotatedMethod<?> annotatedMethod = AnnotatedMethods.findMethod(annotatedType, key); - - Locked config = annotatedMethod.getAnnotation(Locked.class); - if (config == null) - { - config = annotatedType.getAnnotation(Locked.class); - } - final Locked.LockFactory factory = config.factory() != Locked.LockFactory.class ? - Locked.LockFactory.class.cast( - beanManager.getReference(beanManager.resolve( - beanManager.getBeans( - config.factory())), - Locked.LockFactory.class, null)) : this; - - final ReadWriteLock writeLock = factory.newLock(annotatedMethod, config.fair()); - final long timeout = config.timeoutUnit().toMillis(config.timeout()); - final Lock lock = config.operation() == READ ? writeLock.readLock() : writeLock.writeLock(); - - if (timeout > 0) - { - operation = new LockSupplier() - { - @Override - public Lock get() - { - try - { - if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) - { - throw new IllegalStateException("Can't lock for " + key + " in " + timeout + "ms"); - } - } - catch (final InterruptedException e) - { - Thread.interrupted(); - throw new IllegalStateException("Locking interrupted", e); - } - return lock; - } - }; - } - else - { - operation = new LockSupplier() - { - @Override - public Lock get() - { - lock.lock(); - return lock; - } - }; - } - - final LockSupplier existing = lockSuppliers.putIfAbsent(key, operation); - if (existing != null) - { - operation = existing; - } - } - return operation; - } - - @Override - public ReadWriteLock newLock(final AnnotatedMethod<?> method, final boolean fair) - { - final String name = method.getJavaMember().getDeclaringClass().getName(); - ReadWriteLock lock = locks.get(name); - if (lock == null) - { - lock = new ReentrantReadWriteLock(fair); - final ReadWriteLock existing = locks.putIfAbsent(name, lock); - if (existing != null) - { - lock = existing; - } - } - return lock; - } - } - - private interface LockSupplier // yes we miss a bit java 8 there - { - Lock get(); + return lockedStrategy.execute(ic); } }
