View Javadoc

1   package cz.cuni.amis.pogamut.multi.utils.timekey;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.HashMap;
6   import java.util.HashSet;
7   import java.util.List;
8   import java.util.Set;
9   
10  import cz.cuni.amis.pogamut.multi.utils.exception.TimeKeyNotLockedException;
11  import cz.cuni.amis.utils.exception.PogamutException;
12  
13  /**
14   * Singleton class that manages timekey locks and unlocks,
15   * 
16   * @author srlok
17   *
18   */
19  public class TimeKeyManager implements ITimeKeyManager {
20  	
21  	private static class KeyHolder {
22  		
23  		public long data;
24  		
25  		public TimeKey timeKey;
26  		
27  		public KeyHolder() {
28  			this(null, 0);
29  		}
30  		
31  		public KeyHolder(long key, long data) {
32  			this.timeKey = TimeKey.get(key);
33  			this.data = data;
34  		}
35  		
36  		public KeyHolder(TimeKey key, long data) {
37  			this.timeKey = key;
38  			this.data = data;
39  		}
40  
41  	}
42  	
43  	private HashMap<Long, KeyHolder> locks;
44  	
45  	private static Object instanceCreationMutex = new Object();
46  	private static TimeKeyManager instance;
47  	
48  	@Override
49  	public Set<Long> getHeldKeys()
50  	{
51  		synchronized(locks) {
52  			return Collections.unmodifiableSet( new HashSet( locks.keySet() ) );
53  		}
54  	}
55  	
56  	@Override
57  	public String getHeldKeysStr()
58  	{
59  		List<Long> keys = new ArrayList<Long>(getHeldKeys());
60  		Collections.sort(keys);
61  		StringBuffer sb = new StringBuffer();
62  		boolean first = true;
63  		for (Long key : keys) {
64  			if (first) first = false;
65  			else sb.append(", ");
66  			sb.append(key);
67  		}
68  		if (sb.length() == 0) return "nothing";
69  		return sb.toString();
70  	}
71  	
72  	public static TimeKeyManager get() {
73  		if (instance != null) return instance;
74  		synchronized(instanceCreationMutex) {
75  			if (instance != null) return instance;
76  			instance = new TimeKeyManager() ;
77  			return instance;
78  		}		
79  	}
80  	
81  	@Override
82  	public boolean isLocked(TimeKey key) {
83  		return isLocked(key.getTime());
84  	}
85  	
86  	@Override
87  	public boolean isLocked(long time) {
88  		synchronized(locks) {
89  			return locks.containsKey(time);
90  		}
91  	}
92  	
93  	@Override
94  	public void unlock(long key) throws TimeKeyNotLockedException {
95  		synchronized(locks) {
96  			KeyHolder n = locks.get(key);
97  			if (n == null) {
98  				throw new TimeKeyNotLockedException("Trying to lock an unlocked " + key);
99  			}
100 			if (n.data <= 0) {
101 				throw new PogamutException("Locks corrupted! " + key + " locks == " + n + " <= 0, ILLEGAL!", this);
102 			}
103 			if (n.data == 1) {
104 				locks.remove(key);
105 			} else {
106 				n.data -= 1;
107 			}
108 		}
109 	}
110 	
111 	@Override
112 	public void unlockAll(long key) throws TimeKeyNotLockedException {
113 		synchronized(locks) {
114 			KeyHolder n = locks.get(key);
115 			if (n == null) {
116 				throw new TimeKeyNotLockedException("Trying to lock an unlocked " + key);
117 			}
118 			locks.remove(key);			
119 		}
120 	}
121 	
122 	@Override
123 	public void lock(long key) {
124 		synchronized(locks) {
125 			KeyHolder n = locks.get(key);
126 			if (n == null) {
127 				locks.put(key, new KeyHolder(key, 1));
128 			} else {
129 				n.data += 1;
130 			}
131 		}
132 	}
133 	
134 	private TimeKeyManager() {
135 		locks = new HashMap<Long, KeyHolder>();
136 	}
137 
138 	@Override
139 	public void unlockAll() {
140 		synchronized(locks) {
141 			while (locks.size() > 0) {
142 				Long time = locks.keySet().iterator().next();
143 				if (time == null) break;
144 				try {
145 					unlockAll(time);
146 				} catch (TimeKeyNotLockedException e) {
147 				}
148 			}
149 		}
150 	}
151 
152 }