Use the same HttpHeaders optimisations in master as in 4.0

This commit is contained in:
Norman Maurer 2013-11-24 10:19:15 +01:00
parent 0fa6dcefc5
commit f84a50d3cb
3 changed files with 58 additions and 138 deletions

View File

@ -15,12 +15,9 @@
*/
package io.netty.handler.codec.http;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -34,35 +31,13 @@ public class DefaultHttpHeaders extends HttpHeaders {
private static final int BUCKET_SIZE = 17;
private static final Set<String> KNOWN_NAMES = createSet(Names.class);
private static final Set<String> KNOWN_VALUES = createSet(Values.class);
private static Set<String> createSet(Class<?> clazz) {
Set<String> set = new HashSet<String>();
Field[] fields = clazz.getDeclaredFields();
for (Field f: fields) {
int m = f.getModifiers();
if (Modifier.isPublic(m) && Modifier.isStatic(m) && Modifier.isFinal(m)
&& f.getType().isAssignableFrom(String.class)) {
try {
set.add((String) f.get(null));
} catch (Throwable cause) {
// ignore
}
}
}
return set;
}
private static int hash(String name, boolean validate) {
private static int hash(String name) {
int h = 0;
for (int i = name.length() - 1; i >= 0; i --) {
char c = name.charAt(i);
if (validate) {
valideHeaderNameChar(c);
if (c >= 'A' && c <= 'Z') {
c += 32;
}
c = toLowerCase(c);
h = 31 * h + c;
}
@ -76,10 +51,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
}
private static boolean eq(String name1, String name2) {
if (name1 == name2) {
// check for object equality as the user may reuse our static fields in HttpHeaders.Names
return true;
}
int nameLen = name1.length();
if (nameLen != name2.length()) {
return false;
@ -89,7 +60,13 @@ public class DefaultHttpHeaders extends HttpHeaders {
char c1 = name1.charAt(i);
char c2 = name2.charAt(i);
if (c1 != c2) {
if (toLowerCase(c1) != toLowerCase(c2)) {
if (c1 >= 'A' && c1 <= 'Z') {
c1 += 32;
}
if (c2 >= 'A' && c2 <= 'Z') {
c2 += 32;
}
if (c1 != c2) {
return false;
}
}
@ -97,13 +74,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
return true;
}
private static char toLowerCase(char c) {
if (c >= 'A' && c <= 'Z') {
c += 32;
}
return c;
}
private static int index(int hash) {
return hash % BUCKET_SIZE;
}
@ -117,27 +87,25 @@ public class DefaultHttpHeaders extends HttpHeaders {
}
public DefaultHttpHeaders(boolean validate) {
head.before = head.after = head;
this.validate = validate;
head.before = head.after = head;
}
void validateHeaderValue0(String headerValue) {
if (KNOWN_VALUES.contains(headerValue)) {
return;
}
validateHeaderValue(headerValue);
void validateHeaderName0(String headerName) {
validateHeaderName(headerName);
}
@Override
public HttpHeaders add(final String name, final Object value) {
String strVal = toString(value);
boolean validateName = false;
String strVal;
if (validate) {
validateHeaderValue0(strVal);
validateName = !KNOWN_NAMES.contains(name);
validateHeaderName0(name);
strVal = toString(value);
validateHeaderValue(strVal);
} else {
strVal = toString(value);
}
int h = hash(name, validateName);
int h = hash(name);
int i = index(h);
add0(h, i, name, strVal);
return this;
@ -145,17 +113,15 @@ public class DefaultHttpHeaders extends HttpHeaders {
@Override
public HttpHeaders add(String name, Iterable<?> values) {
boolean validateName = false;
if (validate) {
validateName = !KNOWN_NAMES.contains(name);
validateHeaderName0(name);
}
int h = hash(name, validateName);
int h = hash(name);
int i = index(h);
for (Object v: values) {
String vstr = toString(v);
if (validate) {
validateHeaderValue0(vstr);
validateHeaderValue(vstr);
}
add0(h, i, name, vstr);
}
@ -178,7 +144,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
if (name == null) {
throw new NullPointerException("name");
}
int h = hash(name, false);
int h = hash(name);
int i = index(h);
remove0(h, i, name);
return this;
@ -222,14 +188,15 @@ public class DefaultHttpHeaders extends HttpHeaders {
@Override
public HttpHeaders set(final String name, final Object value) {
String strVal = toString(value);
boolean validateName = false;
String strVal;
if (validate) {
validateHeaderValue0(strVal);
validateName = !KNOWN_NAMES.contains(name);
validateHeaderName0(name);
strVal = toString(value);
validateHeaderValue(strVal);
} else {
strVal = toString(value);
}
int h = hash(name, validateName);
int h = hash(name);
int i = index(h);
remove0(h, i, name);
add0(h, i, name, strVal);
@ -241,13 +208,11 @@ public class DefaultHttpHeaders extends HttpHeaders {
if (values == null) {
throw new NullPointerException("values");
}
boolean validateName = false;
if (validate) {
validateName = !KNOWN_NAMES.contains(name);
validateHeaderName0(name);
}
int h = hash(name, validateName);
int h = hash(name);
int i = index(h);
remove0(h, i, name);
@ -257,7 +222,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
}
String strVal = toString(v);
if (validate) {
validateHeaderValue0(strVal);
validateHeaderValue(strVal);
}
add0(h, i, name, strVal);
}
@ -274,15 +239,11 @@ public class DefaultHttpHeaders extends HttpHeaders {
@Override
public String get(final String name) {
return get(name, false);
}
private String get(final String name, boolean last) {
if (name == null) {
throw new NullPointerException("name");
}
int h = hash(name, false);
int h = hash(name);
int i = index(h);
HeaderEntry e = entries[i];
String value = null;
@ -290,9 +251,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
while (e != null) {
if (e.hash == h && eq(name, e.key)) {
value = e.value;
if (last) {
break;
}
}
e = e.next;
@ -308,7 +266,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
LinkedList<String> values = new LinkedList<String>();
int h = hash(name, false);
int h = hash(name);
int i = index(h);
HeaderEntry e = entries[i];
while (e != null) {
@ -340,7 +298,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
@Override
public boolean contains(String name) {
return get(name, true) != null;
return get(name) != null;
}
@Override
@ -354,7 +312,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
throw new NullPointerException("name");
}
int h = hash(name, false);
int h = hash(name);
int i = index(h);
HeaderEntry e = entries[i];
while (e != null) {
@ -472,9 +430,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
if (value == null) {
throw new NullPointerException("value");
}
if (validate) {
validateHeaderValue0(value);
}
validateHeaderValue(value);
String oldValue = this.value;
this.value = value;
return oldValue;

View File

@ -93,44 +93,13 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
}
private static final class TrailingHeaders extends DefaultHttpHeaders {
TrailingHeaders(boolean validateHeaders) {
super(validateHeaders);
TrailingHeaders(boolean validate) {
super(validate);
}
@Override
public HttpHeaders add(String name, Object value) {
if (validate) {
validateName(name);
}
return super.add(name, value);
}
@Override
public HttpHeaders add(String name, Iterable<?> values) {
if (validate) {
validateName(name);
}
return super.add(name, values);
}
@Override
public HttpHeaders set(String name, Iterable<?> values) {
if (validate) {
validateName(name);
}
return super.set(name, values);
}
@Override
public HttpHeaders set(String name, Object value) {
if (validate) {
validateName(name);
}
return super.set(name, value);
}
private static void validateName(String name) {
void validateHeaderName0(String name) {
super.validateHeaderName0(name);
if (name.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH) ||
name.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING) ||
name.equalsIgnoreCase(HttpHeaders.Names.TRAILER)) {

View File

@ -546,14 +546,12 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
*/
public static boolean isKeepAlive(HttpMessage message) {
String connection = message.headers().get(Names.CONNECTION);
boolean close = Values.CLOSE.equalsIgnoreCase(connection);
if (close) {
if (Values.CLOSE.equalsIgnoreCase(connection)) {
return false;
}
if (message.getProtocolVersion().isKeepAliveDefault()) {
return !close;
return !Values.CLOSE.equalsIgnoreCase(connection);
} else {
return Values.KEEP_ALIVE.equalsIgnoreCase(connection);
}
@ -1021,24 +1019,21 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
for (int index = 0; index < headerName.length(); index ++) {
//Actually get the character
char character = headerName.charAt(index);
valideHeaderNameChar(character);
}
}
static void valideHeaderNameChar(char c) {
//Check to see if the character is not an ASCII character
if (c > 127) {
throw new IllegalArgumentException(
"Header name cannot contain non-ASCII characters: " + c);
}
//Check for prohibited characters.
switch (c) {
case '\t': case '\n': case 0x0b: case '\f': case '\r':
case ' ': case ',': case ':': case ';': case '=':
//Check to see if the character is not an ASCII character
if (character > 127) {
throw new IllegalArgumentException(
"Header name cannot contain the following prohibited characters: " +
"=,;: \\t\\r\\n\\v\\f ");
"Header name cannot contain non-ASCII characters: " + headerName);
}
//Check for prohibited characters.
switch (character) {
case '\t': case '\n': case 0x0b: case '\f': case '\r':
case ' ': case ',': case ':': case ';': case '=':
throw new IllegalArgumentException(
"Header name cannot contain the following prohibited characters: " +
"=,;: \\t\\r\\n\\v\\f: " + headerName);
}
}
}