/* * Copyright (c) 2017 Baidu, Inc. All Rights Reserve. * * 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 com.baidu.fsg.dlock.support; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import javax.annotation.PostConstruct; import javax.annotation.Resource; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import com.baidu.fsg.dlock.DistributedReentrantLock; import com.baidu.fsg.dlock.domain.DLockConfig; import com.baidu.fsg.dlock.domain.DLockType; import com.baidu.fsg.dlock.processor.DLockProcessor; import com.baidu.fsg.dlock.utils.EnumUtils; /** * DLockGenerator represents a generator for {@link DistributedReentrantLock} <br> * It will load the lease time of {@link DLockType} configured in file config-dlock.properties, key is DLockType Enum * name, value is lease time(ms). Sample as below:<p> * * <code>CUSTOMER_LOCK=1000</code><br> * <code>XXXXXXXX_LOCK=2000</code> * * @author yutianbao */ @Service public class DLockGenerator { /** Default dlock configuration path */ private static final String DEFAULT_CONF_PATH = "dlock/config-dlock.properties"; @Resource private DLockProcessor lockProcessor; /** * Key for DLockType enum, Value for lease time (ms) */ private Map<DLockType, Integer> lockConfigMap = new HashMap<>(); /** * dlock properties configuration file path */ private String confPath; /** * Load the lease config from properties, and init the lockConfigMap. */ @PostConstruct public void init() { try { // Using default path if no specified confPath = StringUtils.isBlank(confPath) ? DEFAULT_CONF_PATH : confPath; // Load lock config from properties Properties properties = PropertiesLoaderUtils.loadAllProperties(confPath); // Build the lockConfigMap for (Entry<Object, Object> propEntry : properties.entrySet()) { DLockType lockType = EnumUtils.valueOf(DLockType.class, propEntry.getKey().toString()); Integer lease = Integer.valueOf(propEntry.getValue().toString()); if (lockType != null && lease != null) { lockConfigMap.put(lockType, lease); } } } catch (Exception e) { throw new RuntimeException("Load distributed lock config fail", e); } } /** * Get lock with a default lease time configured in the config-dlock.properties * * @param lockType enum DLockType * @param lockTarget * @return */ public Lock gen(DLockType lockType, String lockTarget) { // pre-check Integer lease = lockConfigMap.get(lockType); Assert.notNull(lease, "unfound config for DLockType:" + lockType); return getLockInstance(lockType.name(), lockTarget, lease, TimeUnit.MILLISECONDS); } /** * Get lock with a specified lease time * * @param lockType enum DLockType * @param lockTarget * @param leaseTime * @return */ public Lock gen(DLockType lockType, String lockTarget, int leaseTime) { // pre-check Assert.notNull(lockType, "lockType can't be null!"); Assert.isTrue(leaseTime > 0, "leaseTime must greater than zero!"); return getLockInstance(lockType.name(), lockTarget, leaseTime, TimeUnit.MILLISECONDS); } /** * A free way to make the instance of {@link DistributedReentrantLock} * * @param lockTypeStr * @param lockTarget * @param lease * @param leaseTimeUnit * @return */ public Lock gen(String lockTypeStr, String lockTarget, int lease, TimeUnit leaseTimeUnit) { // pre-check Assert.isTrue(StringUtils.isNotEmpty(lockTypeStr), "lockTypeStr can't be empty!"); Assert.isTrue(lease > 0, "leaseTime must greater than zero!"); Assert.notNull(leaseTimeUnit, "leaseTimeUnit can't be null!"); return getLockInstance(lockTypeStr, lockTarget, lease, leaseTimeUnit); } /** * Get lockConfigMap(unmodifiableMap) */ @SuppressWarnings("unchecked") public Map<DLockType, Integer> getLockConfigMap() { return MapUtils.unmodifiableMap(lockConfigMap); } /** * Generate instance of DistributedReentrantLock */ private Lock getLockInstance(String lockTypeStr, String lockTarget, int lease, TimeUnit leaseTimeUnit) { DLockConfig dlockConfig = new DLockConfig(lockTypeStr, lockTarget, lease, leaseTimeUnit); return new DistributedReentrantLock(dlockConfig, lockProcessor); } /** * Setter for spring field */ public void setConfPath(String confPath) { this.confPath = confPath; } }