author | mbalao |
Wed, 05 Jun 2019 01:42:11 -0300 | |
changeset 55258 | d65d3c37232c |
parent 48985 | 3fbc7f109dad |
permissions | -rw-r--r-- |
2 | 1 |
/* |
48985
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
2 |
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
/* |
|
27 |
* |
|
28 |
* (C) Copyright IBM Corp. 1999 All Rights Reserved. |
|
29 |
* Copyright 1997 The Open Group Research Institute. All rights reserved. |
|
30 |
*/ |
|
31 |
||
32 |
package sun.security.krb5.internal.rcache; |
|
33 |
||
34 |
import sun.security.krb5.internal.Krb5; |
|
18536 | 35 |
|
36 |
import java.util.Iterator; |
|
2 | 37 |
import java.util.LinkedList; |
38 |
import java.util.ListIterator; |
|
39 |
import sun.security.krb5.internal.KerberosTime; |
|
18536 | 40 |
import sun.security.krb5.internal.KrbApErrException; |
2 | 41 |
|
42 |
/** |
|
18536 | 43 |
* This class provides an efficient caching mechanism to store AuthTimeWithHash |
44 |
* from client authenticators. The cache minimizes the memory usage by doing |
|
45 |
* self-cleanup of expired items in the cache. |
|
46 |
* |
|
47 |
* AuthTimeWithHash objects inside a cache are always sorted from big (new) to |
|
32003 | 48 |
* small (old) as determined by {@link AuthTimeWithHash#compareTo}. In the most |
18536 | 49 |
* common case a newcomer should be newer than the first element. |
2 | 50 |
* |
51 |
* @author Yanni Zhang |
|
52 |
*/ |
|
18536 | 53 |
public class AuthList { |
2 | 54 |
|
18536 | 55 |
private final LinkedList<AuthTimeWithHash> entries; |
56 |
private final int lifespan; |
|
11526 | 57 |
|
48985
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
58 |
// entries.getLast().ctime, updated after each cleanup. |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
59 |
private volatile int oldestTime = Integer.MIN_VALUE; |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
60 |
|
2 | 61 |
/** |
18536 | 62 |
* Constructs a AuthList. |
2 | 63 |
*/ |
18536 | 64 |
public AuthList(int lifespan) { |
65 |
this.lifespan = lifespan; |
|
66 |
entries = new LinkedList<>(); |
|
2 | 67 |
} |
68 |
||
69 |
/** |
|
18536 | 70 |
* Puts the authenticator timestamp into the cache in descending order, |
71 |
* and throw an exception if it's already there. |
|
2 | 72 |
*/ |
48985
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
73 |
public synchronized void put(AuthTimeWithHash t, KerberosTime currentTime) |
18536 | 74 |
throws KrbApErrException { |
2 | 75 |
|
18536 | 76 |
if (entries.isEmpty()) { |
77 |
entries.addFirst(t); |
|
48985
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
78 |
oldestTime = t.ctime; |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
79 |
return; |
18536 | 80 |
} else { |
81 |
AuthTimeWithHash temp = entries.getFirst(); |
|
82 |
int cmp = temp.compareTo(t); |
|
83 |
if (cmp < 0) { |
|
84 |
// This is the most common case, newly received authenticator |
|
85 |
// has larger timestamp. |
|
86 |
entries.addFirst(t); |
|
87 |
} else if (cmp == 0) { |
|
88 |
throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT); |
|
89 |
} else { |
|
2 | 90 |
//unless client clock being re-adjusted. |
18536 | 91 |
ListIterator<AuthTimeWithHash> it = entries.listIterator(1); |
92 |
boolean found = false; |
|
2 | 93 |
while (it.hasNext()) { |
94 |
temp = it.next(); |
|
18536 | 95 |
cmp = temp.compareTo(t); |
96 |
if (cmp < 0) { |
|
97 |
// Find an older one, put in front of it |
|
98 |
entries.add(entries.indexOf(temp), t); |
|
99 |
found = true; |
|
2 | 100 |
break; |
18536 | 101 |
} else if (cmp == 0) { |
102 |
throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT); |
|
2 | 103 |
} |
18536 | 104 |
} |
105 |
if (!found) { |
|
106 |
// All is newer than the newcomer. Sigh. |
|
107 |
entries.addLast(t); |
|
2 | 108 |
} |
109 |
} |
|
110 |
} |
|
111 |
||
112 |
// let us cleanup while we are here |
|
18536 | 113 |
long timeLimit = currentTime.getSeconds() - lifespan; |
48985
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
114 |
|
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
115 |
// Only trigger a cleanup when the earliest entry is |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
116 |
// lifespan + 5 sec ago. This ensures a cleanup is done |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
117 |
// at most every 5 seconds so that we don't always |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
118 |
// addLast(removeLast). |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
119 |
if (oldestTime > timeLimit - 5) { |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
120 |
return; |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
121 |
} |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
122 |
|
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
123 |
// and we remove the *enough* old ones (1 lifetime ago) |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
124 |
while (!entries.isEmpty()) { |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
125 |
AuthTimeWithHash removed = entries.removeLast(); |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
126 |
if (removed.ctime >= timeLimit) { |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
127 |
entries.addLast(removed); |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
128 |
oldestTime = removed.ctime; |
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
129 |
return; |
2 | 130 |
} |
131 |
} |
|
48985
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
132 |
|
3fbc7f109dad
8197518: Kerberos krb5 authentication: AuthList's put method leads to performance issue
weijun
parents:
47216
diff
changeset
|
133 |
oldestTime = Integer.MIN_VALUE; |
2 | 134 |
} |
135 |
||
18536 | 136 |
public boolean isEmpty() { |
137 |
return entries.isEmpty(); |
|
2 | 138 |
} |
139 |
||
18536 | 140 |
public String toString() { |
141 |
StringBuilder sb = new StringBuilder(); |
|
142 |
Iterator<AuthTimeWithHash> iter = entries.descendingIterator(); |
|
143 |
int pos = entries.size(); |
|
144 |
while (iter.hasNext()) { |
|
145 |
AuthTimeWithHash at = iter.next(); |
|
146 |
sb.append('#').append(pos--).append(": ") |
|
147 |
.append(at.toString()).append('\n'); |
|
148 |
} |
|
149 |
return sb.toString(); |
|
150 |
} |
|
2 | 151 |
} |