Added methods and @Intern annotation to stream pooled strings (a

la String.intern) as we do class names, by sending the value the 
first time and a short code thereafter (with special handling for 
datagrams, where me must continue sending the mapping until we 
know they've been received).  This is mostly useful for the 
lengthy config names and parameter names of Project X, but it 
could conceivably also be used for things like NamedEvents, which 
stream the same object field names many times in the course of a 
stream.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5797 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Andrzej Kapolka
2009-05-22 22:43:19 +00:00
parent e5172053c8
commit 1bdb2cae16
7 changed files with 345 additions and 13 deletions
@@ -43,10 +43,27 @@ public class UnreliableObjectOutputStream extends ObjectOutputStream
}
/**
* Notes that the receiver has received the mappings for a group of classes, and thus that from
* now on, only the class codes need be sent.
* Sets the reference to the set that will hold the pooled strings for which mappings have been
* written.
*/
public void noteMappingsReceived (Collection<Class<?>> sclasses)
public void setMappedInterns (Set<String> mappedInterns)
{
_mappedInterns = mappedInterns;
}
/**
* Returns a reference to the set of pooled strings for which mappings have been written.
*/
public Set<String> getMappedInterns ()
{
return _mappedInterns;
}
/**
* Notes that the receiver has received the mappings for a group of classes and thus that from
* now on, only the codes need be sent.
*/
public void noteClassMappingsReceived (Collection<Class<?>> sclasses)
{
// sanity check
if (_classmap == null) {
@@ -63,6 +80,74 @@ public class UnreliableObjectOutputStream extends ObjectOutputStream
}
}
/**
* Notes that the receiver has received the mappings for a group of interns and thus that from
* now on, only the codes need be sent.
*/
public void noteInternMappingsReceived (Collection<String> sinterns)
{
// sanity check
if (_internmap == null) {
throw new RuntimeException("Missing intern map");
}
// make each intern's code positive to signify that we no longer need to send metadata
for (String sintern : sinterns) {
Short code = _internmap.get(sintern);
if (code == null) {
throw new RuntimeException("No intern mapping for " + sintern);
}
short scode = code;
if (scode < 0) {
_internmap.put(sintern, (short)-code);
}
}
}
@Override // documentation inherited
protected Short createInternMapping (short code)
{
// the negative intern code indicates that we must rewrite the metadata for the first
// instance in each go-round; when we are notified that the other side has cached the
// mapping, we can simply write the (positive) code
return (short)-code;
}
@Override // documentation inherited
protected void writeNewInternMapping (short code, String value)
throws IOException
{
writeInternMapping(code, value);
}
@Override // documentation inherited
protected void writeExistingInternMapping (short code, String value)
throws IOException
{
// if the other side has received the mapping, we need only send the reference
if (code > 0) {
writeShort(code);
// likewise if we've written the value once this go-round
} else if (_mappedInterns.contains(value)) {
writeShort(-code);
// otherwise, we must retransmit the mapping
} else {
writeInternMapping(code, value);
}
}
@Override // documentation inherited
protected void writeInternMapping (int code, String value)
throws IOException
{
super.writeInternMapping(code, value);
// note that we've written the mapping
_mappedInterns.add(value);
}
@Override // documentation inherited
protected ClassMapping createClassMapping (short code, Class<?> sclass, Streamer streamer)
{
@@ -109,4 +194,7 @@ public class UnreliableObjectOutputStream extends ObjectOutputStream
/** The set of classes for which we have written mappings. */
protected Set<Class<?>> _mappedClasses = new HashSet<Class<?>>();
/** The set of pooled strings for which we have written mappings. */
protected Set<String> _mappedInterns = new HashSet<String>();
}