blob: 1856265f7256d95b84bbde570fb465fbcb27db93 [file] [log] [blame]
/*
* 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.ambari.server.orm;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.ambari.annotations.TransactionalLock.LockArea;
import org.apache.ambari.server.configuration.Configuration;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;
/**
* The {@link TransactionalLocks} class is used to manage the locks associated
* with each {@link LockArea}. It's a singlegon that shoudl always be injected.
*/
@Singleton
public class TransactionalLocks {
/**
* Used to lookup whether {@link LockArea}s are enabled.
*/
private final Configuration m_configuration;
/**
* Manages the locks for each class which uses the {@link Transactional}
* annotation.
*/
private final ConcurrentHashMap<LockArea, ReadWriteLock> m_locks;
/**
* Constructor.
*
*/
@Inject
private TransactionalLocks(Configuration configuration) {
m_configuration = configuration;
m_locks = new ConcurrentHashMap<>();
for (LockArea lockArea : LockArea.values()) {
final ReadWriteLock lock;
if (lockArea.isEnabled(m_configuration)) {
lock = new ReentrantReadWriteLock(true);
} else {
lock = new NoOperationReadWriteLock();
}
m_locks.put(lockArea, lock);
}
}
/**
* Gets a lock for the specified lock area. There is a 1:1 relationship
* between a lock area and a lock.
* <p/>
* If the {@link LockArea} is not enabled, then this will return an empty
* {@link Lock} implementation which doesn't actually lock anything.
*
* @param lockArea
* the lock area to get the lock for (not {@code null}).
* @return the lock to use for the specified lock area (never {@code null}).
*/
public ReadWriteLock getLock(LockArea lockArea) {
return m_locks.get(lockArea);
}
/**
* A dummy implementation of a {@link ReadWriteLock} that returns locks which
* only NOOP. This is used for cases where dependant code doesn't want to
* {@code if/else} all over the place.
*/
private final static class NoOperationReadWriteLock implements ReadWriteLock {
private final Lock m_readLock = new NoOperationLock();
private final Lock m_writeLock = new NoOperationLock();
/**
* {@inheritDoc}
*/
@Override
public Lock readLock() {
return m_readLock;
}
/**
* {@inheritDoc}
*/
@Override
public Lock writeLock() {
return m_writeLock;
}
}
/**
* A dummy implementation of a {@link Lock} that only NOOPs. This is used for
* cases where dependant code doesn't want to {@code if/else} all over the
* place.
*/
private final static class NoOperationLock implements Lock {
/**
* NOOP
* <p/>
* {@inheritDoc}
*/
@Override
public void lock() {
}
/**
* NOOP
* <p/>
* {@inheritDoc}
*/
@Override
public void lockInterruptibly() throws InterruptedException {
}
/**
* NOOP, returns {@code true} always.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean tryLock() {
return true;
}
/**
* NOOP, returns {@code true} always.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return true;
}
/**
* NOOP
* <p/>
* {@inheritDoc}
*/
@Override
public void unlock() {
}
/**
* NOOP
* <p/>
* {@inheritDoc}
*/
@Override
public Condition newCondition() {
return null;
}
}
}