001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.concurrent;
016    
017    import java.util.Map;
018    import java.util.concurrent.ConcurrentHashMap;
019    import java.util.concurrent.locks.ReentrantLock;
020    
021    /**
022     * @author Shuyang Zhou
023     */
024    public class LockRegistry {
025    
026            public static ReentrantLock allocateLock(String groupName, String key) {
027                    ConcurrentHashMap<String, ReentrantLock> lockGroup = _lockGroupMap.get(
028                            groupName);
029    
030                    if (lockGroup == null) {
031                            lockGroup = new ConcurrentHashMap<String, ReentrantLock>();
032    
033                            ConcurrentHashMap<String, ReentrantLock> oldLockGroup =
034                                    _lockGroupMap.putIfAbsent(groupName, lockGroup);
035    
036                            if (oldLockGroup != null) {
037                                    lockGroup = oldLockGroup;
038                            }
039                    }
040    
041                    ReentrantLock lock = lockGroup.get(key);
042    
043                    if (lock == null) {
044                            lock = new ReentrantLock();
045    
046                            ReentrantLock oldLock = lockGroup.putIfAbsent(key, lock);
047    
048                            if (oldLock != null) {
049                                    lock = oldLock;
050                            }
051                    }
052    
053                    return lock;
054            }
055    
056            public static ReentrantLock finallyFreeLock(
057                    String groupName, String key, boolean unlock) {
058    
059                    if (_prematureLockReleases.containsKey(groupName + key)) {
060                            return freeLock(groupName, key, unlock);
061                    }
062    
063                    return null;
064            }
065    
066            public static void freeAllLock() {
067                    freeAllLock(false);
068            }
069    
070            public static void freeAllLock(boolean unlock) {
071                    if (unlock == true) {
072                            for (Map<String, ReentrantLock> lockGroup :
073                                            _lockGroupMap.values()) {
074    
075                                    for (ReentrantLock lock : lockGroup.values()) {
076                                            lock.unlock();
077                                    }
078                            }
079                    }
080    
081                    _lockGroupMap.clear();
082                    _prematureLockReleases.clear();
083            }
084    
085            public static Map<String, ReentrantLock> freeLock(String groupName) {
086                    return freeLock(groupName, false);
087            }
088    
089            public static Map<String, ReentrantLock> freeLock(
090                    String groupName, boolean unlock) {
091    
092                    Map<String, ReentrantLock> lockGroup = _lockGroupMap.remove(groupName);
093    
094                    if (lockGroup == null) {
095                            _prematureLockReleases.put(groupName, _dummyValue);
096    
097                            return null;
098                    }
099    
100                    if (unlock == true) {
101                            for (ReentrantLock lock : lockGroup.values()) {
102                                    lock.unlock();
103                            }
104    
105                            _prematureLockReleases.remove(groupName);
106                    }
107    
108                    return lockGroup;
109            }
110    
111            public static ReentrantLock freeLock(String groupName, String key) {
112                    return freeLock(groupName, key, false);
113            }
114    
115            public static ReentrantLock freeLock(
116                    String groupName, String key, boolean unlock) {
117    
118                    Map<String, ReentrantLock> lockGroup = _lockGroupMap.get(groupName);
119    
120                    String prematureLockReleasesKey = groupName + key;
121    
122                    if (lockGroup == null) {
123                            _prematureLockReleases.put(prematureLockReleasesKey, _dummyValue);
124    
125                            return null;
126                    }
127    
128                    ReentrantLock lock = lockGroup.remove(key);
129    
130                    if (lock == null) {
131                            _prematureLockReleases.put(prematureLockReleasesKey, _dummyValue);
132    
133                            return null;
134                    }
135    
136                    if (unlock) {
137                            lock.unlock();
138    
139                            _prematureLockReleases.remove(prematureLockReleasesKey);
140                    }
141    
142                    return lock;
143            }
144    
145            public static ReentrantLock getLock(String groupName, String key) {
146                    ConcurrentHashMap<String, ReentrantLock> lockGroup = _lockGroupMap.get(
147                            groupName);
148    
149                    if (lockGroup == null) {
150                            return null;
151                    }
152    
153                    return lockGroup.get(key);
154            }
155    
156            private static Object _dummyValue = new Object();
157            private static ConcurrentHashMap
158                    <String, ConcurrentHashMap<String, ReentrantLock>>
159                            _lockGroupMap =
160                                    new ConcurrentHashMap
161                                            <String, ConcurrentHashMap<String, ReentrantLock>>();
162            private static Map<String, Object> _prematureLockReleases =
163                    new ConcurrentHashMap<String, Object>();
164    
165    }