
io.seata.server.lock.AbstractLockManager Maven / Gradle / Ivy
/*
* Copyright 1999-2019 Seata.io Group.
*
* Licensed 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 io.seata.server.lock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import io.seata.common.XID;
import io.seata.common.util.CollectionUtils;
import io.seata.common.util.StringUtils;
import io.seata.core.exception.TransactionException;
import io.seata.core.lock.Locker;
import io.seata.core.lock.RowLock;
import io.seata.core.model.LockStatus;
import io.seata.server.session.BranchSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The type Abstract lock manager.
*
* @author zhangsen
*/
public abstract class AbstractLockManager implements LockManager {
/**
* The constant LOGGER.
*/
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractLockManager.class);
@Override
public boolean acquireLock(BranchSession branchSession) throws TransactionException {
return acquireLock(branchSession, true, false);
}
@Override
public boolean acquireLock(BranchSession branchSession, boolean autoCommit, boolean skipCheckLock) throws TransactionException {
if (branchSession == null) {
throw new IllegalArgumentException("branchSession can't be null for memory/file locker.");
}
String lockKey = branchSession.getLockKey();
if (StringUtils.isNullOrEmpty(lockKey)) {
// no lock
return true;
}
// get locks of branch
List locks = collectRowLocks(branchSession);
if (CollectionUtils.isEmpty(locks)) {
// no lock
return true;
}
return getLocker(branchSession).acquireLock(locks, autoCommit, skipCheckLock);
}
@Override
public boolean releaseLock(BranchSession branchSession) throws TransactionException {
if (branchSession == null) {
throw new IllegalArgumentException("branchSession can't be null for memory/file locker.");
}
List locks = collectRowLocks(branchSession);
try {
return getLocker(branchSession).releaseLock(locks);
} catch (Exception t) {
LOGGER.error("unLock error, branchSession:{}", branchSession, t);
return false;
}
}
@Override
public boolean isLockable(String xid, String resourceId, String lockKey) throws TransactionException {
if (StringUtils.isBlank(lockKey)) {
// no lock
return true;
}
List locks = collectRowLocks(lockKey, resourceId, xid);
try {
return getLocker().isLockable(locks);
} catch (Exception t) {
LOGGER.error("isLockable error, xid:{} resourceId:{}, lockKey:{}", xid, resourceId, lockKey, t);
return false;
}
}
@Override
public void cleanAllLocks() throws TransactionException {
getLocker().cleanAllLocks();
}
/**
* Gets locker.
*
* @return the locker
*/
protected Locker getLocker() {
return getLocker(null);
}
/**
* Gets locker.
*
* @param branchSession the branch session
* @return the locker
*/
protected abstract Locker getLocker(BranchSession branchSession);
@Override
public List collectRowLocks(BranchSession branchSession) {
if (branchSession == null || StringUtils.isBlank(branchSession.getLockKey())) {
return Collections.emptyList();
}
String lockKey = branchSession.getLockKey();
String resourceId = branchSession.getResourceId();
String xid = branchSession.getXid();
long transactionId = branchSession.getTransactionId();
long branchId = branchSession.getBranchId();
return collectRowLocks(lockKey, resourceId, xid, transactionId, branchId);
}
/**
* Collect row locks list.
*
* @param lockKey the lock key
* @param resourceId the resource id
* @param xid the xid
* @return the list
*/
protected List collectRowLocks(String lockKey, String resourceId, String xid) {
return collectRowLocks(lockKey, resourceId, xid, XID.getTransactionId(xid), null);
}
/**
* Collect row locks list.
*
* @param lockKey the lock key
* @param resourceId the resource id
* @param xid the xid
* @param transactionId the transaction id
* @param branchID the branch id
* @return the list
*/
protected List collectRowLocks(String lockKey, String resourceId, String xid, Long transactionId,
Long branchID) {
List locks = new ArrayList<>();
String[] tableGroupedLockKeys = lockKey.split(";");
for (String tableGroupedLockKey : tableGroupedLockKeys) {
int idx = tableGroupedLockKey.indexOf(":");
if (idx < 0) {
return locks;
}
String tableName = tableGroupedLockKey.substring(0, idx);
String mergedPKs = tableGroupedLockKey.substring(idx + 1);
if (StringUtils.isBlank(mergedPKs)) {
return locks;
}
String[] pks = mergedPKs.split(",");
if (pks == null || pks.length == 0) {
return locks;
}
for (String pk : pks) {
if (StringUtils.isNotBlank(pk)) {
RowLock rowLock = new RowLock();
rowLock.setXid(xid);
rowLock.setTransactionId(transactionId);
rowLock.setBranchId(branchID);
rowLock.setTableName(tableName);
rowLock.setPk(pk);
rowLock.setResourceId(resourceId);
locks.add(rowLock);
}
}
}
return locks;
}
@Override
public void updateLockStatus(String xid, LockStatus lockStatus) {
this.getLocker().updateLockStatus(xid, lockStatus);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy