mirror of https://github.com/grpc/grpc-java.git
Remove serializable distinction for Metadata
This does make use of the fact we are no longer using Multimap. Doing entries() for ArrayListMultimap must create a new Map.Entry for every entry. Since we are now using HashMap, we are able to use entries() with no extra cost. Merging particular Keys no longer needs to deserialize.
This commit is contained in:
parent
a2292faf43
commit
8fe667676c
|
|
@ -102,7 +102,6 @@ public abstract class Metadata {
|
||||||
// Use LinkedHashMap for consistent ordering for tests.
|
// Use LinkedHashMap for consistent ordering for tests.
|
||||||
private final Map<String, List<MetadataEntry>> store =
|
private final Map<String, List<MetadataEntry>> store =
|
||||||
new LinkedHashMap<String, List<MetadataEntry>>();
|
new LinkedHashMap<String, List<MetadataEntry>>();
|
||||||
private final boolean serializable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor called by the transport layer when it receives binary metadata.
|
* Constructor called by the transport layer when it receives binary metadata.
|
||||||
|
|
@ -113,15 +112,12 @@ public abstract class Metadata {
|
||||||
String name = new String(binaryValues[i], US_ASCII);
|
String name = new String(binaryValues[i], US_ASCII);
|
||||||
storeAdd(name, new MetadataEntry(name.endsWith(BINARY_HEADER_SUFFIX), binaryValues[++i]));
|
storeAdd(name, new MetadataEntry(name.endsWith(BINARY_HEADER_SUFFIX), binaryValues[++i]));
|
||||||
}
|
}
|
||||||
this.serializable = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor called by the application layer when it wants to send metadata.
|
* Constructor called by the application layer when it wants to send metadata.
|
||||||
*/
|
*/
|
||||||
private Metadata() {
|
private Metadata() {}
|
||||||
this.serializable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void storeAdd(String name, MetadataEntry value) {
|
private void storeAdd(String name, MetadataEntry value) {
|
||||||
List<MetadataEntry> values = store.get(name);
|
List<MetadataEntry> values = store.get(name);
|
||||||
|
|
@ -225,15 +221,6 @@ public abstract class Metadata {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Can this metadata be serialized. Metadata constructed from raw binary or ascii values
|
|
||||||
* cannot be serialized without merging it into a serializable instance using
|
|
||||||
* {@link #merge(Metadata, java.util.Set)}
|
|
||||||
*/
|
|
||||||
public boolean isSerializable() {
|
|
||||||
return serializable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize all the metadata entries.
|
* Serialize all the metadata entries.
|
||||||
*
|
*
|
||||||
|
|
@ -248,13 +235,18 @@ public abstract class Metadata {
|
||||||
* <p>This method is intended for transport use only.
|
* <p>This method is intended for transport use only.
|
||||||
*/
|
*/
|
||||||
public byte[][] serialize() {
|
public byte[][] serialize() {
|
||||||
Preconditions.checkState(serializable, "Can't serialize raw metadata");
|
|
||||||
// One *2 for keys+values, one *2 to prevent resizing if a single key has multiple values
|
// One *2 for keys+values, one *2 to prevent resizing if a single key has multiple values
|
||||||
List<byte[]> serialized = new ArrayList<byte[]>(store.size() * 2 * 2);
|
List<byte[]> serialized = new ArrayList<byte[]>(store.size() * 2 * 2);
|
||||||
for (List<MetadataEntry> values : store.values()) {
|
for (Map.Entry<String, List<MetadataEntry>> keyEntry : store.entrySet()) {
|
||||||
for (int i = 0; i < values.size(); i++) {
|
for (int i = 0; i < keyEntry.getValue().size(); i++) {
|
||||||
MetadataEntry entry = values.get(i);
|
MetadataEntry entry = keyEntry.getValue().get(i);
|
||||||
serialized.add(entry.key.asciiName());
|
byte[] asciiName;
|
||||||
|
if (entry.key != null) {
|
||||||
|
asciiName = entry.key.asciiName();
|
||||||
|
} else {
|
||||||
|
asciiName = keyEntry.getKey().getBytes(US_ASCII);
|
||||||
|
}
|
||||||
|
serialized.add(asciiName);
|
||||||
serialized.add(entry.getSerialized());
|
serialized.add(entry.getSerialized());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,24 +255,14 @@ public abstract class Metadata {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a simple merge of two sets of metadata.
|
* Perform a simple merge of two sets of metadata.
|
||||||
* <p>
|
|
||||||
* Note that we can't merge non-serializable metadata into serializable.
|
|
||||||
* </p>
|
|
||||||
*/
|
*/
|
||||||
public void merge(Metadata other) {
|
public void merge(Metadata other) {
|
||||||
Preconditions.checkNotNull(other);
|
Preconditions.checkNotNull(other);
|
||||||
if (this.serializable) {
|
for (Map.Entry<String, List<MetadataEntry>> keyEntry : other.store.entrySet()) {
|
||||||
if (!other.serializable) {
|
for (int i = 0; i < keyEntry.getValue().size(); i++) {
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Cannot merge non-serializable metadata into serializable metadata without keys");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (List<MetadataEntry> values : other.store.values()) {
|
|
||||||
for (int i = 0; i < values.size(); i++) {
|
|
||||||
MetadataEntry entry = values.get(i);
|
|
||||||
// Must copy the MetadataEntries since they are mutated. If the two Metadata objects are
|
// Must copy the MetadataEntries since they are mutated. If the two Metadata objects are
|
||||||
// used from different threads it would cause thread-safety issues.
|
// used from different threads it would cause thread-safety issues.
|
||||||
storeAdd(entry.key.name(), new MetadataEntry(entry));
|
storeAdd(keyEntry.getKey(), new MetadataEntry(keyEntry.getValue().get(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -288,15 +270,17 @@ public abstract class Metadata {
|
||||||
/**
|
/**
|
||||||
* Merge values for the given set of keys into this set of metadata.
|
* Merge values for the given set of keys into this set of metadata.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public void merge(Metadata other, Set<Key<?>> keys) {
|
public void merge(Metadata other, Set<Key<?>> keys) {
|
||||||
Preconditions.checkNotNull(other);
|
Preconditions.checkNotNull(other);
|
||||||
for (Key<?> key : keys) {
|
for (Key<?> key : keys) {
|
||||||
if (other.containsKey(key)) {
|
List<MetadataEntry> values = other.store.get(key.name);
|
||||||
Iterable<?> values = other.getAll(key);
|
if (values == null) {
|
||||||
for (Object value : values) {
|
continue;
|
||||||
put((Key) key, value);
|
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < values.size(); i++) {
|
||||||
|
// Must copy the MetadataEntries since they are mutated. If the two Metadata objects are
|
||||||
|
// used from different threads it would cause thread-safety issues.
|
||||||
|
storeAdd(key.name, new MetadataEntry(values.get(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,17 +134,24 @@ public class MetadataTest {
|
||||||
assertSame(lance, raw.get(KEY));
|
assertSame(lance, raw.get(KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test
|
||||||
public void testFailSerializeRaw() {
|
public void testSerializeRaw() {
|
||||||
Metadata.Headers raw = new Metadata.Headers(KEY.asciiName(), LANCE_BYTES);
|
Metadata.Headers raw = new Metadata.Headers(KEY.asciiName(), LANCE_BYTES);
|
||||||
raw.serialize();
|
byte[][] serialized = raw.serialize();
|
||||||
|
assertArrayEquals(serialized[0], KEY.asciiName());
|
||||||
|
assertArrayEquals(serialized[1], LANCE_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testFailMergeRawIntoSerializable() {
|
public void testMergeByteConstructed() {
|
||||||
Metadata.Headers raw = new Metadata.Headers(KEY.asciiName(), LANCE_BYTES);
|
Metadata.Headers raw = new Metadata.Headers(KEY.asciiName(), LANCE_BYTES);
|
||||||
Metadata.Headers serializable = new Metadata.Headers();
|
Metadata.Headers serializable = new Metadata.Headers();
|
||||||
serializable.merge(raw);
|
serializable.merge(raw);
|
||||||
|
|
||||||
|
byte[][] serialized = serializable.serialize();
|
||||||
|
assertArrayEquals(serialized[0], KEY.asciiName());
|
||||||
|
assertArrayEquals(serialized[1], LANCE_BYTES);
|
||||||
|
assertEquals(new Fish(LANCE), serializable.get(KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue