Improve the performance of copying header sets when hashing and name validation are equivalent.
Motivation: Headers and groups of headers are frequently copied and the current mechanism is slower than it needs to be. Modifications: Skip name validation and hash computation when they are not necessary. Fix emergent bug in CombinedHttpHeaders identified with better testing Fix memory leak in DefaultHttp2Headers when clearing Added benchmarks Result: Faster header copying and some collateral bug fixes
This commit is contained in:
parent
187efca9aa
commit
6e108cb96a
@ -18,10 +18,12 @@ package io.netty.handler.codec.http;
|
||||
import io.netty.handler.codec.DefaultHeaders;
|
||||
import io.netty.handler.codec.ValueConverter;
|
||||
import io.netty.util.HashingStrategy;
|
||||
import io.netty.handler.codec.Headers;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
|
||||
import static io.netty.util.internal.StringUtil.COMMA;
|
||||
@ -75,6 +77,50 @@ public class CombinedHttpHeaders extends DefaultHttpHeaders {
|
||||
super(nameHashingStrategy, valueConverter, nameValidator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinedHttpHeadersImpl add(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||
// Override the fast-copy mechanism used by DefaultHeaders
|
||||
if (headers == this) {
|
||||
throw new IllegalArgumentException("can't add to itself.");
|
||||
}
|
||||
if (headers instanceof CombinedHttpHeadersImpl) {
|
||||
if (isEmpty()) {
|
||||
// Can use the fast underlying copy
|
||||
addImpl(headers);
|
||||
} else {
|
||||
// Values are already escaped so don't escape again
|
||||
for (Map.Entry<? extends CharSequence, ? extends CharSequence> header : headers) {
|
||||
addEscapedValue(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<? extends CharSequence, ? extends CharSequence> header : headers) {
|
||||
add(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinedHttpHeadersImpl set(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||
if (headers == this) {
|
||||
return this;
|
||||
}
|
||||
clear();
|
||||
return add(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinedHttpHeadersImpl setAll(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||
if (headers == this) {
|
||||
return this;
|
||||
}
|
||||
for (CharSequence key : headers.names()) {
|
||||
remove(key);
|
||||
}
|
||||
return add(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinedHttpHeadersImpl add(CharSequence name, CharSequence value) {
|
||||
return addEscapedValue(name, StringUtil.escapeCsv(value));
|
||||
|
@ -15,12 +15,14 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http;
|
||||
|
||||
import io.netty.handler.codec.DefaultHeaders;
|
||||
import io.netty.handler.codec.http.HttpHeadersTestUtils.HeaderValue;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static io.netty.util.AsciiString.contentEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class CombinedHttpHeadersTest {
|
||||
@ -41,6 +43,60 @@ public class CombinedHttpHeadersTest {
|
||||
assertCsvValues(headers, HeaderValue.FIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addCombinedHeadersWhenEmpty() {
|
||||
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||
final CombinedHttpHeaders otherHeaders = newCombinedHttpHeaders();
|
||||
otherHeaders.add(HEADER_NAME, "a");
|
||||
otherHeaders.add(HEADER_NAME, "b");
|
||||
headers.add(otherHeaders);
|
||||
assertEquals("a,b", headers.get(HEADER_NAME).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addCombinedHeadersWhenNotEmpty() {
|
||||
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||
headers.add(HEADER_NAME, "a");
|
||||
final CombinedHttpHeaders otherHeaders = newCombinedHttpHeaders();
|
||||
otherHeaders.add(HEADER_NAME, "b");
|
||||
otherHeaders.add(HEADER_NAME, "c");
|
||||
headers.add(otherHeaders);
|
||||
assertEquals("a,b,c", headers.get(HEADER_NAME).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCombinedHeadersWhenNotEmpty() {
|
||||
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||
headers.add(HEADER_NAME, "a");
|
||||
final CombinedHttpHeaders otherHeaders = newCombinedHttpHeaders();
|
||||
otherHeaders.add(HEADER_NAME, "b");
|
||||
otherHeaders.add(HEADER_NAME, "c");
|
||||
headers.set(otherHeaders);
|
||||
assertEquals("b,c", headers.get(HEADER_NAME).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addUncombinedHeaders() {
|
||||
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||
headers.add(HEADER_NAME, "a");
|
||||
final DefaultHttpHeaders otherHeaders = new DefaultHttpHeaders();
|
||||
otherHeaders.add(HEADER_NAME, "b");
|
||||
otherHeaders.add(HEADER_NAME, "c");
|
||||
headers.add(otherHeaders);
|
||||
assertEquals("a,b,c", headers.get(HEADER_NAME).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setUncombinedHeaders() {
|
||||
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||
headers.add(HEADER_NAME, "a");
|
||||
final DefaultHttpHeaders otherHeaders = new DefaultHttpHeaders();
|
||||
otherHeaders.add(HEADER_NAME, "b");
|
||||
otherHeaders.add(HEADER_NAME, "c");
|
||||
headers.set(otherHeaders);
|
||||
assertEquals("b,c", headers.get(HEADER_NAME).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addCharSequencesCsvWithValueContainingComma() {
|
||||
final CombinedHttpHeaders headers = newCombinedHttpHeaders();
|
||||
|
@ -316,7 +316,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
||||
|
||||
@Override
|
||||
public T addObject(K name, Iterable<?> values) {
|
||||
checkNotNull(values, "values");
|
||||
for (Object value : values) {
|
||||
addObject(name, value);
|
||||
}
|
||||
@ -325,7 +324,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
||||
|
||||
@Override
|
||||
public T addObject(K name, Object... values) {
|
||||
checkNotNull(values, "values");
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
addObject(name, values[i]);
|
||||
}
|
||||
@ -379,25 +377,39 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
||||
|
||||
@Override
|
||||
public T add(Headers<? extends K, ? extends V, ?> headers) {
|
||||
checkNotNull(headers, "headers");
|
||||
if (headers == this) {
|
||||
throw new IllegalArgumentException("can't add to itself.");
|
||||
}
|
||||
addImpl(headers);
|
||||
return thisT();
|
||||
}
|
||||
|
||||
protected void addImpl(Headers<? extends K, ? extends V, ?> headers) {
|
||||
if (headers instanceof DefaultHeaders) {
|
||||
@SuppressWarnings("unchecked")
|
||||
DefaultHeaders<K, V, T> defaultHeaders = (DefaultHeaders<K, V, T>) headers;
|
||||
HeaderEntry<K, V> e = defaultHeaders.head.after;
|
||||
final DefaultHeaders<? extends K, ? extends V, T> defaultHeaders =
|
||||
(DefaultHeaders<? extends K, ? extends V, T>) headers;
|
||||
HeaderEntry<? extends K, ? extends V> e = defaultHeaders.head.after;
|
||||
if (defaultHeaders.hashingStrategy == hashingStrategy &&
|
||||
defaultHeaders.nameValidator == nameValidator) {
|
||||
// Fastest copy
|
||||
while (e != defaultHeaders.head) {
|
||||
add0(e.hash, index(e.hash), e.key, e.value);
|
||||
e = e.after;
|
||||
}
|
||||
} else {
|
||||
// Fast copy
|
||||
while (e != defaultHeaders.head) {
|
||||
add(e.key, e.value);
|
||||
e = e.after;
|
||||
}
|
||||
return thisT();
|
||||
}
|
||||
} else {
|
||||
// Slow copy
|
||||
for (Entry<? extends K, ? extends V> header : headers) {
|
||||
add(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
return thisT();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -459,7 +471,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
||||
@Override
|
||||
public T setObject(K name, Iterable<?> values) {
|
||||
nameValidator.validateName(name);
|
||||
checkNotNull(values, "values");
|
||||
|
||||
int h = hashingStrategy.hashCode(name);
|
||||
int i = index(h);
|
||||
@ -478,7 +489,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
||||
@Override
|
||||
public T setObject(K name, Object... values) {
|
||||
nameValidator.validateName(name);
|
||||
checkNotNull(values, "values");
|
||||
|
||||
int h = hashingStrategy.hashCode(name);
|
||||
int i = index(h);
|
||||
@ -541,36 +551,20 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
|
||||
|
||||
@Override
|
||||
public T set(Headers<? extends K, ? extends V, ?> headers) {
|
||||
checkNotNull(headers, "headers");
|
||||
if (headers == this) {
|
||||
return thisT();
|
||||
}
|
||||
if (headers != this) {
|
||||
clear();
|
||||
if (headers instanceof DefaultHeaders) {
|
||||
@SuppressWarnings("unchecked")
|
||||
DefaultHeaders<K, V, T> defaultHeaders = (DefaultHeaders<K, V, T>) headers;
|
||||
HeaderEntry<K, V> e = defaultHeaders.head.after;
|
||||
while (e != defaultHeaders.head) {
|
||||
add(e.key, e.value);
|
||||
e = e.after;
|
||||
}
|
||||
} else {
|
||||
add(headers);
|
||||
addImpl(headers);
|
||||
}
|
||||
return thisT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T setAll(Headers<? extends K, ? extends V, ?> headers) {
|
||||
checkNotNull(headers, "headers");
|
||||
if (headers == this) {
|
||||
return thisT();
|
||||
}
|
||||
if (headers != this) {
|
||||
for (K key : headers.names()) {
|
||||
remove(key);
|
||||
}
|
||||
for (Entry<? extends K, ? extends V> entry : headers) {
|
||||
add(entry.getKey(), entry.getValue());
|
||||
addImpl(headers);
|
||||
}
|
||||
return thisT();
|
||||
}
|
||||
|
@ -152,6 +152,59 @@ public class DefaultHeadersTest {
|
||||
assertFalse(headers.contains(of("name"), of("value1")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopy() throws Exception {
|
||||
TestDefaultHeaders headers = newInstance();
|
||||
headers.addBoolean(of("boolean"), true);
|
||||
headers.addLong(of("long"), Long.MAX_VALUE);
|
||||
headers.addInt(of("int"), Integer.MIN_VALUE);
|
||||
headers.addShort(of("short"), Short.MAX_VALUE);
|
||||
headers.addChar(of("char"), Character.MAX_VALUE);
|
||||
headers.addByte(of("byte"), Byte.MAX_VALUE);
|
||||
headers.addDouble(of("double"), Double.MAX_VALUE);
|
||||
headers.addFloat(of("float"), Float.MAX_VALUE);
|
||||
long millis = System.currentTimeMillis();
|
||||
headers.addTimeMillis(of("millis"), millis);
|
||||
headers.addObject(of("object"), "Hello World");
|
||||
headers.add(of("name"), of("value"));
|
||||
|
||||
headers = newInstance().add(headers);
|
||||
|
||||
assertTrue(headers.containsBoolean(of("boolean"), true));
|
||||
assertFalse(headers.containsBoolean(of("boolean"), false));
|
||||
|
||||
assertTrue(headers.containsLong(of("long"), Long.MAX_VALUE));
|
||||
assertFalse(headers.containsLong(of("long"), Long.MIN_VALUE));
|
||||
|
||||
assertTrue(headers.containsInt(of("int"), Integer.MIN_VALUE));
|
||||
assertFalse(headers.containsInt(of("int"), Integer.MAX_VALUE));
|
||||
|
||||
assertTrue(headers.containsShort(of("short"), Short.MAX_VALUE));
|
||||
assertFalse(headers.containsShort(of("short"), Short.MIN_VALUE));
|
||||
|
||||
assertTrue(headers.containsChar(of("char"), Character.MAX_VALUE));
|
||||
assertFalse(headers.containsChar(of("char"), Character.MIN_VALUE));
|
||||
|
||||
assertTrue(headers.containsByte(of("byte"), Byte.MAX_VALUE));
|
||||
assertFalse(headers.containsLong(of("byte"), Byte.MIN_VALUE));
|
||||
|
||||
assertTrue(headers.containsDouble(of("double"), Double.MAX_VALUE));
|
||||
assertFalse(headers.containsDouble(of("double"), Double.MIN_VALUE));
|
||||
|
||||
assertTrue(headers.containsFloat(of("float"), Float.MAX_VALUE));
|
||||
assertFalse(headers.containsFloat(of("float"), Float.MIN_VALUE));
|
||||
|
||||
assertTrue(headers.containsTimeMillis(of("millis"), millis));
|
||||
// This test doesn't work on midnight, January 1, 1970 UTC
|
||||
assertFalse(headers.containsTimeMillis(of("millis"), 0));
|
||||
|
||||
assertTrue(headers.containsObject(of("object"), "Hello World"));
|
||||
assertFalse(headers.containsObject(of("object"), ""));
|
||||
|
||||
assertTrue(headers.contains(of("name"), of("value")));
|
||||
assertFalse(headers.contains(of("name"), of("value1")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canMixConvertedAndNormalValues() {
|
||||
TestDefaultHeaders headers = newInstance();
|
||||
|
@ -15,12 +15,14 @@
|
||||
*/
|
||||
package io.netty.microbench.headers;
|
||||
|
||||
import io.netty.handler.codec.Headers;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http2.DefaultHttp2Headers;
|
||||
import io.netty.microbench.util.AbstractMicrobenchmark;
|
||||
import io.netty.util.AsciiString;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Level;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
@ -34,43 +36,78 @@ import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.infra.Blackhole;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Threads(1)
|
||||
@State(Scope.Benchmark)
|
||||
@Warmup(iterations = 5)
|
||||
@Measurement(iterations = 5)
|
||||
@Fork(1)
|
||||
@Warmup(iterations = 10)
|
||||
@Measurement(iterations = 10)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
public class HeadersBenchmark extends AbstractMicrobenchmark {
|
||||
|
||||
private static String toHttpName(String name) {
|
||||
return (name.startsWith(":")) ? name.substring(1) : name;
|
||||
}
|
||||
|
||||
private static String toHttp2Name(String name) {
|
||||
name = name.toLowerCase();
|
||||
return (name.equals("host")) ? "xhost" : name;
|
||||
}
|
||||
|
||||
@Param
|
||||
ExampleHeaders.HeaderExample exampleHeader;
|
||||
|
||||
AsciiString[] httpNames;
|
||||
AsciiString[] http2Names;
|
||||
AsciiString[] httpValues;
|
||||
|
||||
DefaultHttpHeaders httpHeaders;
|
||||
DefaultHttp2Headers http2Headers;
|
||||
DefaultHttpHeaders emptyHttpHeaders;
|
||||
DefaultHttp2Headers emptyHttp2Headers;
|
||||
DefaultHttpHeaders emptyHttpHeadersNoValidate;
|
||||
DefaultHttp2Headers emptyHttp2HeadersNoValidate;
|
||||
SlowHeaders slowHttp2Headers;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setup() {
|
||||
Map<String, String> headers = ExampleHeaders.EXAMPLES.get(exampleHeader);
|
||||
httpNames = new AsciiString[headers.size()];
|
||||
http2Names = new AsciiString[headers.size()];
|
||||
httpValues = new AsciiString[headers.size()];
|
||||
httpHeaders = new DefaultHttpHeaders(false);
|
||||
http2Headers = new DefaultHttp2Headers(false);
|
||||
int idx = 0;
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
String name = header.getKey();
|
||||
String httpName = toHttpName(name);
|
||||
String http2Name = toHttp2Name(name);
|
||||
String value = header.getValue();
|
||||
httpNames[idx] = new AsciiString(name);
|
||||
httpNames[idx] = new AsciiString(httpName);
|
||||
http2Names[idx] = new AsciiString(http2Name);
|
||||
httpValues[idx] = new AsciiString(value);
|
||||
httpHeaders.add(httpNames[idx], httpValues[idx]);
|
||||
http2Headers.add(http2Names[idx], httpValues[idx]);
|
||||
idx++;
|
||||
httpHeaders.add(new AsciiString(name), new AsciiString(value));
|
||||
http2Headers.add(new AsciiString(name), new AsciiString(value));
|
||||
}
|
||||
slowHttp2Headers = new SlowHeaders(http2Headers);
|
||||
emptyHttpHeaders = new DefaultHttpHeaders(true);
|
||||
emptyHttp2Headers = new DefaultHttp2Headers(true);
|
||||
emptyHttpHeadersNoValidate = new DefaultHttpHeaders(false);
|
||||
emptyHttp2HeadersNoValidate = new DefaultHttp2Headers(false);
|
||||
}
|
||||
|
||||
@Setup(Level.Invocation)
|
||||
public void setupEmptyHeaders() {
|
||||
emptyHttpHeaders.clear();
|
||||
emptyHttp2Headers .clear();
|
||||
emptyHttpHeadersNoValidate.clear();
|
||||
emptyHttp2HeadersNoValidate.clear();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@ -111,7 +148,7 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public void http2Remove(Blackhole bh) {
|
||||
for (AsciiString name : httpNames) {
|
||||
for (AsciiString name : http2Names) {
|
||||
bh.consume(http2Headers.remove(name));
|
||||
}
|
||||
}
|
||||
@ -119,7 +156,7 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public void http2Get(Blackhole bh) {
|
||||
for (AsciiString name : httpNames) {
|
||||
for (AsciiString name : http2Names) {
|
||||
bh.consume(http2Headers.get(name));
|
||||
}
|
||||
}
|
||||
@ -128,8 +165,8 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public DefaultHttp2Headers http2Put() {
|
||||
DefaultHttp2Headers headers = new DefaultHttp2Headers(false);
|
||||
for (int i = 0; i < httpNames.length; i++) {
|
||||
headers.add(httpNames[i], httpValues[i]);
|
||||
for (int i = 0; i < http2Names.length; i++) {
|
||||
headers.add(http2Names[i], httpValues[i]);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
@ -141,4 +178,540 @@ public class HeadersBenchmark extends AbstractMicrobenchmark {
|
||||
bh.consume(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public void httpAddAllFastest(Blackhole bh) {
|
||||
bh.consume(emptyHttpHeadersNoValidate.add(httpHeaders));
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public void httpAddAllFast(Blackhole bh) {
|
||||
bh.consume(emptyHttpHeaders.add(httpHeaders));
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public void http2AddAllFastest(Blackhole bh) {
|
||||
bh.consume(emptyHttp2HeadersNoValidate.add(http2Headers));
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public void http2AddAllFast(Blackhole bh) {
|
||||
bh.consume(emptyHttp2Headers.add(http2Headers));
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
public void http2AddAllSlow(Blackhole bh) {
|
||||
bh.consume(emptyHttp2Headers.add(slowHttp2Headers));
|
||||
}
|
||||
|
||||
private static final class SlowHeaders implements Headers<CharSequence, CharSequence, SlowHeaders> {
|
||||
private final Headers<CharSequence, CharSequence, ? extends Headers> delegate;
|
||||
private SlowHeaders(Headers<CharSequence, CharSequence, ? extends Headers> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence get(CharSequence name) {
|
||||
return delegate.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence get(CharSequence name, CharSequence defaultValue) {
|
||||
return delegate.get(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getAndRemove(CharSequence name) {
|
||||
return delegate.getAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getAndRemove(CharSequence name, CharSequence defaultValue) {
|
||||
return delegate.getAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CharSequence> getAll(CharSequence name) {
|
||||
return delegate.getAll(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CharSequence> getAllAndRemove(CharSequence name) {
|
||||
return delegate.getAllAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBoolean(CharSequence name) {
|
||||
return delegate.getBoolean(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(CharSequence name, boolean defaultValue) {
|
||||
return delegate.getBoolean(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getByte(CharSequence name) {
|
||||
return delegate.getByte(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(CharSequence name, byte defaultValue) {
|
||||
return delegate.getByte(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character getChar(CharSequence name) {
|
||||
return delegate.getChar(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getChar(CharSequence name, char defaultValue) {
|
||||
return delegate.getChar(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short getShort(CharSequence name) {
|
||||
return delegate.getShort(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(CharSequence name, short defaultValue) {
|
||||
return delegate.getShort(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getInt(CharSequence name) {
|
||||
return delegate.getInt(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(CharSequence name, int defaultValue) {
|
||||
return delegate.getInt(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLong(CharSequence name) {
|
||||
return delegate.getLong(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(CharSequence name, long defaultValue) {
|
||||
return delegate.getLong(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getFloat(CharSequence name) {
|
||||
return delegate.getFloat(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(CharSequence name, float defaultValue) {
|
||||
return delegate.getFloat(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDouble(CharSequence name) {
|
||||
return delegate.getDouble(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(CharSequence name, double defaultValue) {
|
||||
return delegate.getDouble(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTimeMillis(CharSequence name) {
|
||||
return delegate.getTimeMillis(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeMillis(CharSequence name, long defaultValue) {
|
||||
return delegate.getTimeMillis(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBooleanAndRemove(CharSequence name) {
|
||||
return delegate.getBooleanAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBooleanAndRemove(CharSequence name, boolean defaultValue) {
|
||||
return delegate.getBooleanAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getByteAndRemove(CharSequence name) {
|
||||
return delegate.getByteAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByteAndRemove(CharSequence name, byte defaultValue) {
|
||||
return delegate.getByteAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character getCharAndRemove(CharSequence name) {
|
||||
return delegate.getCharAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getCharAndRemove(CharSequence name, char defaultValue) {
|
||||
return delegate.getCharAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short getShortAndRemove(CharSequence name) {
|
||||
return delegate.getShortAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShortAndRemove(CharSequence name, short defaultValue) {
|
||||
return delegate.getShortAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntAndRemove(CharSequence name) {
|
||||
return delegate.getIntAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntAndRemove(CharSequence name, int defaultValue) {
|
||||
return delegate.getIntAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLongAndRemove(CharSequence name) {
|
||||
return delegate.getLongAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongAndRemove(CharSequence name, long defaultValue) {
|
||||
return delegate.getLongAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getFloatAndRemove(CharSequence name) {
|
||||
return delegate.getFloatAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloatAndRemove(CharSequence name, float defaultValue) {
|
||||
return delegate.getFloatAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDoubleAndRemove(CharSequence name) {
|
||||
return delegate.getDoubleAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDoubleAndRemove(CharSequence name, double defaultValue) {
|
||||
return delegate.getDoubleAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTimeMillisAndRemove(CharSequence name) {
|
||||
return delegate.getTimeMillisAndRemove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeMillisAndRemove(CharSequence name, long defaultValue) {
|
||||
return delegate.getTimeMillisAndRemove(name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(CharSequence name) {
|
||||
return delegate.contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(CharSequence name, CharSequence value) {
|
||||
return delegate.contains(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsObject(CharSequence name, Object value) {
|
||||
return delegate.containsObject(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsBoolean(CharSequence name, boolean value) {
|
||||
return delegate.containsBoolean(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsByte(CharSequence name, byte value) {
|
||||
return delegate.containsByte(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsChar(CharSequence name, char value) {
|
||||
return delegate.containsChar(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsShort(CharSequence name, short value) {
|
||||
return delegate.containsShort(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsInt(CharSequence name, int value) {
|
||||
return delegate.containsInt(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsLong(CharSequence name, long value) {
|
||||
return delegate.containsLong(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsFloat(CharSequence name, float value) {
|
||||
return delegate.containsFloat(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsDouble(CharSequence name, double value) {
|
||||
return delegate.containsDouble(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsTimeMillis(CharSequence name, long value) {
|
||||
return delegate.containsTimeMillis(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<CharSequence> names() {
|
||||
return delegate.names();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders add(CharSequence name, CharSequence value) {
|
||||
delegate.add(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders add(CharSequence name, Iterable<? extends CharSequence> values) {
|
||||
delegate.add(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders add(CharSequence name, CharSequence... values) {
|
||||
delegate.add(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addObject(CharSequence name, Object value) {
|
||||
delegate.addObject(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addObject(CharSequence name, Iterable<?> values) {
|
||||
delegate.addObject(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addObject(CharSequence name, Object... values) {
|
||||
delegate.addObject(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addBoolean(CharSequence name, boolean value) {
|
||||
delegate.addBoolean(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addByte(CharSequence name, byte value) {
|
||||
delegate.addByte(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addChar(CharSequence name, char value) {
|
||||
delegate.addChar(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addShort(CharSequence name, short value) {
|
||||
delegate.addShort(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addInt(CharSequence name, int value) {
|
||||
delegate.addInt(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addLong(CharSequence name, long value) {
|
||||
delegate.addLong(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addFloat(CharSequence name, float value) {
|
||||
delegate.addFloat(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addDouble(CharSequence name, double value) {
|
||||
delegate.addDouble(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders addTimeMillis(CharSequence name, long value) {
|
||||
delegate.addTimeMillis(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders add(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||
delegate.add(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders set(CharSequence name, CharSequence value) {
|
||||
delegate.set(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders set(CharSequence name, Iterable<? extends CharSequence> values) {
|
||||
delegate.set(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders set(CharSequence name, CharSequence... values) {
|
||||
delegate.set(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setObject(CharSequence name, Object value) {
|
||||
delegate.setObject(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setObject(CharSequence name, Iterable<?> values) {
|
||||
delegate.setObject(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setObject(CharSequence name, Object... values) {
|
||||
delegate.setObject(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setBoolean(CharSequence name, boolean value) {
|
||||
delegate.setBoolean(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setByte(CharSequence name, byte value) {
|
||||
delegate.setByte(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setChar(CharSequence name, char value) {
|
||||
delegate.setChar(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setShort(CharSequence name, short value) {
|
||||
delegate.setShort(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setInt(CharSequence name, int value) {
|
||||
delegate.setInt(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setLong(CharSequence name, long value) {
|
||||
delegate.setLong(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setFloat(CharSequence name, float value) {
|
||||
delegate.setFloat(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setDouble(CharSequence name, double value) {
|
||||
delegate.setDouble(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setTimeMillis(CharSequence name, long value) {
|
||||
delegate.setTimeMillis(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders set(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||
delegate.set(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders setAll(Headers<? extends CharSequence, ? extends CharSequence, ?> headers) {
|
||||
delegate.setAll(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(CharSequence name) {
|
||||
return delegate.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlowHeaders clear() {
|
||||
delegate.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry<CharSequence, CharSequence>> iterator() {
|
||||
return delegate.iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user