All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jizcode.lock.LockManager Maven / Gradle / Ivy

There is a newer version: 1.0.14-BETA
Show newest version
package jizcode.lock;


import jizcode.base.Jizcode;
import jizcode.base.tool.CacheTool;
import jizcode.base.util.ConvertUtil;
import jizcode.base.util.DateUtil;
import jizcode.base.util.StringUtils;

import java.util.Date;
import java.util.Map;

class LockManager {
    private static Object LockObj = new Object();

    public static boolean addKey(CacheTool cache, String key, int timeout) {
        if (timeout <= 0) {
            return false;
        }
        try {
            Date nowForCheck = new Date();
            String actualKey = String.format(CacheTool.PrefixForLockPrimay, key);
            if (!canLock(cache, key, nowForCheck)) {
                return false;
            }

            synchronized (LockObj) {
                if (!canLock(cache, key, nowForCheck)) {
                    return false;
                }
                String timeString = String.format("%s;%s", timeout, DateUtil.toDateTimeString(DateUtil.addSeconds(new Date(), timeout)));
                cache.set(actualKey, timeString);
                return true;
            }
        } catch (Exception e) {
            return false;
        }
    }

    public static void removeKey(CacheTool cache, String key) {
        String actualKey = String.format(CacheTool.PrefixForLockPrimay, key);
        try {
            synchronized (LockObj) {
                cache.remove(actualKey);
            }
        } catch (Exception e) {
        }
    }

    public static boolean addKeys(CacheTool cache, String[] keys, int timeout) {
        if (timeout <= 0) {
            return false;
        }
        try {
            Date nowForCheck = new Date();
            if (!canLock(cache, keys, nowForCheck)) {
                return false;
            }
            synchronized (LockObj) {
                if (!canLock(cache, keys, nowForCheck)) {
                    return false;
                }
                String keyValue = String.format("%s;%s", timeout, DateUtil.toDateTimeString(DateUtil.addSeconds(new Date(), timeout)));
                for (int index = 0; index < keys.length; index++) {
                    String actualKey = String.format(CacheTool.PrefixForLockPrimay, keys[index]);
                    cache.set(actualKey, keyValue);
                }
                return true;
            }
        } catch (Exception e) {
            Jizcode.getLog().error("add keys error", e);
            return false;
        }
    }

    public static void removeKeys(CacheTool cache, String[] keys) {
        try {
            synchronized (LockObj) {
                for (int index = 0; index < keys.length; index++) {
                    String actualKey = String.format(CacheTool.PrefixForLockPrimay, keys[index]);
                    cache.tryRemove(actualKey);
                }
            }
        } catch (Exception e) {
        }
    }

    /**
     * 添加注册关联key
     * @param cache
     * @param primaryKey
     * @param relativekey
     * @param timeout
     */
    public static boolean addKey(CacheTool cache, String primaryKey, String relativekey, int timeout) {
        if (timeout <= 0) {
            return false;
        }
        try {
            Date nowForCheck = new Date();
            String actualPrimaryKey = String.format(CacheTool.PrefixForLockPrimay, primaryKey);
            String actualRelativeKey = String.format(CacheTool.PrefixForLockRelative, relativekey);
            if(!canLock(cache, primaryKey, nowForCheck)) {
                return false;
            }
            synchronized (LockObj) {
                if (!canLock(cache, primaryKey, nowForCheck)) {
                    return false;
                }
                String timeString = String.format("%s;%s", timeout, DateUtil.toDateTimeString(DateUtil.addSeconds(new Date(), timeout)));
                // l0:primaryKey    timeout;time;relativeKey
                cache.set(actualPrimaryKey, String.format("%s;%s", timeString, relativekey));
                Jizcode.getLog().debug("add lock:{} time:{} timeout:{}", primaryKey, timeString, timeout);
                // l1:relativeKey   l1:c 0
                //                       primaryKey time
                //                       primaryKey time
                int count = ConvertUtil.tryToInteger(cache.mapGet(actualRelativeKey, CacheTool.LockRelativeCountKey), 0);
                String relativeTimeString = cache.mapGet(actualRelativeKey, primaryKey);
                if(StringUtils.isNullOrEmpty((relativeTimeString))) {
                    count++;
                }
                cache.mapAdd(actualRelativeKey, CacheTool.LockRelativeCountKey, String.valueOf(count));
                cache.mapAdd(actualRelativeKey, primaryKey, timeString);
                Jizcode.getLog().debug("add relative lock:{} for:{} count:{}", primaryKey, relativekey, count);
                return true;
            }
        } catch (Exception e) {
            Jizcode.getLog().error("addKey error", e);
            return false;
        }
    }

    public static void removeKey(CacheTool cache, String primaryKey, String relativekey) {
        String actualPrimaryKey = String.format(CacheTool.PrefixForLockPrimay, primaryKey);
        String actualRelativeKey = String.format(CacheTool.PrefixForLockRelative, relativekey);
        synchronized (LockObj) {
            cache.tryRemove(actualPrimaryKey);

            int count = ConvertUtil.tryToInteger(cache.mapGet(actualRelativeKey, CacheTool.LockRelativeCountKey), 0);
            String relativeTimeString = cache.mapGet(actualRelativeKey, primaryKey);
            if(!StringUtils.isNullOrEmpty((relativeTimeString))) {
                count--;
            }
            cache.tryMapAdd(actualRelativeKey, CacheTool.LockRelativeCountKey, String.valueOf(count));
            cache.tryMapRemove(actualRelativeKey, primaryKey);
            Jizcode.getLog().debug("remove relative lock:{} for:{}", primaryKey, relativekey);
        }
    }

    public static boolean addKeys(CacheTool cache, String[] primaryKeys, String relativeKey, int timeout) {
        if (timeout <= 0) {
            return false;
        }
        try {
            Date nowForCheck = new Date();
            if (!canLock(cache, primaryKeys, nowForCheck)) {
                return false;
            }
            synchronized (LockObj) {
                if (!canLock(cache, primaryKeys, nowForCheck)) {
                    return false;
                }
                String timeString = String.format("%s;%s", timeout, DateUtil.toDateTimeString(DateUtil.addSeconds(new Date(), timeout)));
                for(int index = 0; index < primaryKeys.length; index++) {
                    String primaryKey = primaryKeys[index];
                    String actualPrimaryKey = String.format(CacheTool.PrefixForLockPrimay, primaryKey);
                    String actualRelativeKey = String.format(CacheTool.PrefixForLockRelative, relativeKey);
                    // l0:primaryKey    timeout;time;relativeKey
                    cache.set(actualPrimaryKey, String.format("%s;%s", timeString, relativeKey));
                    Jizcode.getLog().debug("add lock:{} time:{} timeout:{}", primaryKey, timeString, timeout);
                    // l1:relativeKey   l1:c 0
                    //                       primaryKey time
                    //                       primaryKey time
                    int count = ConvertUtil.tryToInteger(cache.mapGet(actualRelativeKey, CacheTool.LockRelativeCountKey), 0);
                    String relativeTimeString = cache.mapGet(actualRelativeKey, primaryKey);
                    if (StringUtils.isNullOrEmpty((relativeTimeString))) {
                        count++;
                    }
                    cache.mapAdd(actualRelativeKey, CacheTool.LockRelativeCountKey, String.valueOf(count));
                    cache.mapAdd(actualRelativeKey, primaryKey, timeString);
                    Jizcode.getLog().debug("add relative lock:{} for:{} count:{}", primaryKey, relativeKey, count);
                }
                return true;
            }
        } catch (Exception e) {
            Jizcode.getLog().error("add keys error", e);
            return false;
        }
    }

    public static void removeKeys(CacheTool cache, String[] primaryKeys, String relativeKey) {
        try {
            synchronized (LockObj) {
                for (int index = 0; index < primaryKeys.length; index++) {
                    String primaryKey = primaryKeys[index];
                    String actualPrimaryKey = String.format(CacheTool.PrefixForLockPrimay, primaryKey);
                    String actualRelativeKey = String.format(CacheTool.PrefixForLockRelative, relativeKey);
                    cache.tryRemove(actualPrimaryKey);

                    int count = ConvertUtil.tryToInteger(cache.mapGet(actualRelativeKey, CacheTool.LockRelativeCountKey), 0);
                    String relativeTimeString = cache.mapGet(actualRelativeKey, primaryKey);
                    if(!StringUtils.isNullOrEmpty((relativeTimeString))) {
                        count--;
                    }
                    cache.tryMapAdd(actualRelativeKey, CacheTool.LockRelativeCountKey, String.valueOf(count));
                    cache.tryMapRemove(actualRelativeKey, primaryKey);
                    Jizcode.getLog().debug("remove relative lock:{} for:{}", primaryKey, relativeKey);
                }
            }
        } catch (Exception e) {
        }
    }

    //#region private method
    private static boolean canLock(CacheTool cache,
                                   String primaryKey,
                                   Date nowForCheck) {
        String actualPrimaryKey = String.format(CacheTool.PrefixForLockPrimay, primaryKey);
        String actualRelativeKey = String.format(CacheTool.PrefixForLockRelative, primaryKey);
        boolean canLock = true;
        // 检查自己有没有被锁
        String primaryLockValue = cache.tryGet(actualPrimaryKey, null);
        if (!StringUtils.isNullOrEmpty(primaryLockValue)) {
            String[] value = primaryLockValue.split(";");
            int timeoutFromCache = ConvertUtil.tryToInteger(value[0], 0);
            Date timeFromCache = ConvertUtil.tryToDate(value[1], DateUtil.MinDate);
            if (DateUtil.getDiffSeconds(nowForCheck, timeFromCache) < timeoutFromCache) {
                Jizcode.getLog().debug("{} has lock time:{}, timeout:{}", primaryKey, value[1], timeoutFromCache);
                canLock = false;
            }
        }
        if (!canLock) {
            return canLock;
        }
        // 检查是否有被别人锁
        int relativeLockCount = ConvertUtil.tryToInteger(cache.tryMapGet(actualRelativeKey, CacheTool.LockRelativeCountKey), 0);
        if (relativeLockCount > 0){
            Map relativeMap = cache.tryMap(actualRelativeKey);
            if(relativeMap != null) {
                for(Map.Entry entry : relativeMap.entrySet()) {
                    String[] value = entry.getValue().split(";");
                    int timeoutFromCache = ConvertUtil.tryToInteger(value[0], 0);
                    Date timeFromCache = ConvertUtil.tryToDate(value[1], DateUtil.MinDate);
                    if(DateUtil.getDiffSeconds(nowForCheck, timeFromCache) <= timeoutFromCache){
                        Jizcode.getLog().debug("{} has relative lock {}, time:{}, timeout:{}", primaryKey, entry.getKey(), value[1], timeoutFromCache);
                        canLock = false;
                        break;
                    }
                }
            }
        }
        return canLock;
    }

    private static boolean canLock(CacheTool cache,
                                   String[] primaryKeys,
                                   Date nowForCheck) {
        for(int index = 0; index < primaryKeys.length; index++) {
            if(!canLock(cache, primaryKeys[index], nowForCheck)){
                return false;
            }
        }
        return true;
    }
    //endregion
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy