1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.sift;
15
16 import java.util.HashMap;
17 import java.util.LinkedList;
18 import java.util.List;
19 import java.util.Map;
20
21 import ch.qos.logback.core.Appender;
22 import ch.qos.logback.core.CoreConstants;
23
24
25
26
27
28
29 public class AppenderTrackerImpl<E> implements AppenderTracker<E> {
30
31 Map<String, Entry> map = new HashMap<String, Entry>();
32
33 Entry head;
34 Entry tail;
35
36 long lastCheck = 0;
37
38 AppenderTrackerImpl() {
39 head = new Entry(null, null, 0);
40 tail = head;
41 }
42
43
44 public synchronized void put(String key, Appender<E> value, long timestamp) {
45 Entry entry = map.get(key);
46 if (entry == null) {
47 entry = new Entry(key, value, timestamp);
48 map.put(key, entry);
49 }
50 moveToTail(entry);
51 }
52
53 public synchronized Appender<E> get(String key, long timestamp) {
54 Entry existing = map.get(key);
55 if (existing == null) {
56 return null;
57 } else {
58 existing.setTimestamp(timestamp);
59 moveToTail(existing);
60 return existing.value;
61 }
62 }
63
64
65 public synchronized void stopStaleAppenders(long now) {
66 if (lastCheck + CoreConstants.MILLIS_IN_ONE_SECOND > now) {
67 return;
68 }
69 lastCheck = now;
70 while (head.value != null && isEntryStale(head,now)) {
71 Appender<E> appender = head.value;
72 appender.stop();
73 removeHead();
74 }
75 }
76
77
78
79
80
81 public synchronized void stopAndRemoveNow(String key) {
82 Entry e = head;
83 Entry found = null;
84 while (e != tail) {
85 if(key.equals(e.key)) {
86 found = e;
87 break;
88 }
89 e = e.next;
90 }
91 if(found != null) {
92 rearrangePreexistingLinks(e);
93 map.remove(key);
94 Appender<E> appender = e.value;
95 appender.stop();
96 }
97 }
98
99 public List<String> keyList() {
100 List<String> result = new LinkedList<String>();
101 Entry e = head;
102 while (e != tail) {
103 result.add(e.key);
104 e = e.next;
105 }
106 return result;
107 }
108
109
110 final private boolean isEntryStale(Entry entry, long now) {
111 return ((entry.timestamp + THRESHOLD) < now);
112 }
113
114
115 private void removeHead() {
116
117 map.remove(head.key);
118 head = head.next;
119 head.prev = null;
120 }
121
122 private void moveToTail(Entry e) {
123 rearrangePreexistingLinks(e);
124 rearrangeTailLinks(e);
125 }
126
127 private void rearrangePreexistingLinks(Entry e) {
128 if (e.prev != null) {
129 e.prev.next = e.next;
130 }
131 if (e.next != null) {
132 e.next.prev = e.prev;
133 }
134 if (head == e) {
135 head = e.next;
136 }
137 }
138
139 private void rearrangeTailLinks(Entry e) {
140 if (head == tail) {
141 head = e;
142 }
143 Entry preTail = tail.prev;
144 if (preTail != null) {
145 preTail.next = e;
146 }
147 e.prev = preTail;
148 e.next = tail;
149 tail.prev = e;
150 }
151
152 public void dump() {
153 Entry e = head;
154 System.out.print("N:");
155 while (e != null) {
156
157 System.out.print(e.key + ", ");
158 e = e.next;
159 }
160 System.out.println();
161 }
162
163
164
165 public List<Appender<E>> valueList() {
166 List<Appender<E>> result = new LinkedList<Appender<E>>();
167 Entry e = head;
168 while (e != tail) {
169 result.add(e.value);
170 e = e.next;
171 }
172 return result;
173 }
174
175
176 private class Entry {
177 Entry next;
178 Entry prev;
179
180 String key;
181 Appender<E> value;
182 long timestamp;
183
184 Entry(String k, Appender<E> v, long timestamp) {
185 this.key = k;
186 this.value = v;
187 this.timestamp = timestamp;
188 }
189
190
191
192
193
194 public void setTimestamp(long timestamp) {
195 this.timestamp = timestamp;
196 }
197
198 @Override
199 public int hashCode() {
200 final int prime = 31;
201 int result = 1;
202 result = prime * result + ((key == null) ? 0 : key.hashCode());
203 return result;
204 }
205
206 @Override
207 public boolean equals(Object obj) {
208 if (this == obj)
209 return true;
210 if (obj == null)
211 return false;
212 if (getClass() != obj.getClass())
213 return false;
214 final Entry other = (Entry) obj;
215 if (key == null) {
216 if (other.key != null)
217 return false;
218 } else if (!key.equals(other.key))
219 return false;
220 if (value == null) {
221 if (other.value != null)
222 return false;
223 } else if (!value.equals(other.value))
224 return false;
225 return true;
226 }
227
228 @Override
229 public String toString() {
230 return "(" + key + ", " + value + ")";
231 }
232 }
233 }