Commit 96d766c0 authored by Jonathan Mace's avatar Jonathan Mace

Add baggagecontext static api

parent db6c0903
......@@ -13,23 +13,4 @@
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
......@@ -14,6 +14,32 @@
</parent>
<dependencies>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>baggagecontext-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>brown.tracingplane</groupId>
<artifactId>baggagecontext-noopimpl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
package brown.tracingplane;
import java.nio.ByteBuffer;
/**
* <p>
* The static methods on the {@link Baggage} class mirror the methods implemented by {@link BaggageProvider}. Calling
* any of these static methods will simply invoke the corresponding method on the current process's registered
* {@link BaggageProvider}.
* </p>
*
* <p>
* To register a {@link BaggageProvider}, you must set the <code>baggage.provider</code> property to the appropriate
* class name.
* </p>
*
*/
public class Baggage {
private static final BaggageProvider<BaggageContext> provider = DefaultBaggageProvider.getWrapped();
/** Not instantiable */
private Baggage() {}
/**
* @return a new instance of {@link B}, which may be null to indicate an empty baggage
*/
public BaggageContext newInstance() {
return provider.newInstance();
}
/**
* Discards <code>baggage</code>, indicating that the instance will not be used again. This method is useful, but
* not required. Its purpose is to enable {@link BaggageContext} implementations to do things like reference
* counting, which is an optimization. Failing to discard baggage instances will have no bad side effects.
*
* @param baggage a baggage context
*/
public void discard(BaggageContext baggage) {
provider.discard(baggage);
}
/**
* Create and return a branched copy <code>from</code>. Typically, this will just duplicate <code>from</code> or
* increment a reference count. Sometimes it will create a new instance, or even modify the contents of
* <code>from</code>.
*
* @param from a baggage instance, possibly null
* @return a baggage instance branched from <code>from</code>, possibly null
*/
public BaggageContext branch(BaggageContext from) {
return provider.branch(from);
}
/**
* Merge the contents of <code>left</code> and <code>right</code> and return as baggage. <code>left</code> and
* <code>right</code> should be treated as discarded (or reused) after this method call.
*
* @param left a baggage instance, possibly null
* @param right a baggage instance, possibly null
* @return a baggage instance with merged contents from <code>left</code> and <code>right</code>
*/
public BaggageContext join(BaggageContext left, BaggageContext right) {
return provider.join(left, right);
}
/**
* Deserialize the provided serialized baggage representation.
*
* @param serialized a serialized baggage
* @param offset offset into the array where the baggage bytes begin
* @param length lenft of the baggage bytes
* @return a deserialized baggage instance, possibly null
*/
public BaggageContext deserialize(byte[] serialized, int offset, int length) {
return provider.deserialize(serialized, offset, length);
}
/**
* Deserialize the provided serialized baggage representation.
*
* @param buf a serialized baggage
* @return a deserialized baggage instance, possibly null
*/
public BaggageContext deserialize(ByteBuffer buf) {
return provider.deserialize(buf);
}
/**
* Serialize the provided baggage instance to its byte representation. This method should behave as though
* {@link #branch(Baggage)} is also being called prior to serialization.
*
* @param baggage a baggage instance to serialize, possibly null
* @return the serialized representation of <code>baggage</code>, which might be null or an empty byte array
*/
public byte[] serialize(BaggageContext baggage) {
return provider.serialize(baggage);
}
/**
* Serialize the provided baggage instance to its byte representation and trim the baggage so that its serialized
* size is {@code <= maximumSerializedSize}. This method should behave as though {@link #branch(Baggage)} is also
* being called prior to serialization.
*
* @param baggage a baggage instance to serialize, possibly null
* @param maximumSerializedSize the maximum size in bytes of the serialized baggage.
* @return the serialized representation of <code>baggage</code>, which might be null or an empty byte array
*/
public byte[] serialize(BaggageContext baggage, int maximumSerializedSize) {
return provider.serialize(baggage, maximumSerializedSize);
}
}
package brown.tracingplane;
import java.nio.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>
* Wraps a {@link BaggageProvider} and provides equivalent methods but on generic {@link BaggageContext} instances
* rather than any specific subclass. Logs errors and returns null if the types provided are incompatible with the
* wrapped provider's types.
* </p>
*/
@SuppressWarnings("unchecked")
class BaggageProviderProxy<B extends BaggageContext> implements BaggageProvider<BaggageContext> {
private static final Logger log = LoggerFactory.getLogger(BaggageProviderProxy.class);
private final BaggageProvider<B> provider; // The wrapped provider implementation
static <B extends BaggageContext> BaggageProvider<BaggageContext> wrap(BaggageProvider<B> provider) {
return new BaggageProviderProxy<B>(provider);
}
private BaggageProviderProxy(BaggageProvider<B> provider) {
this.provider = provider;
}
@Override
public boolean isValid(BaggageContext baggage) {
return provider.isValid(baggage);
}
@Override
public BaggageContext newInstance() {
return provider.newInstance();
}
@Override
public void discard(BaggageContext baggage) {
if (provider.isValid(baggage)) {
provider.discard((B) baggage);
} else {
log.warn("discarding incompatible baggage to {}.discard, baggage class is {}",
provider.getClass().getName(), baggage.getClass().getName());
}
}
@Override
public BaggageContext branch(BaggageContext from) {
if (provider.isValid(from)) {
return provider.branch((B) from);
} else {
log.warn("discarding incompatible baggage to {}.branch; baggage class is {}", provider.getClass().getName(),
from.getClass().getName());
}
return null;
}
@Override
public BaggageContext join(BaggageContext left, BaggageContext right) {
if (provider.isValid(left) && provider.isValid(right)) {
return provider.join((B) left, (B) right);
} else if (provider.isValid(left)) {
log.warn("discarding incompatible right baggage to {}.join; left baggage class is {}; right baggage class is {}",
provider.getClass().getName(), left.getClass().getName(), right.getClass().getName());
} else if (provider.isValid(right)) {
log.warn("discarding incompatible left baggage to {}.join; left baggage class is {}; right baggage class is {}",
provider.getClass().getName(), left.getClass().getName(), right.getClass().getName());
} else {
log.warn("discarding incompatible baggage to {}.join; left baggage class is {}; right baggage class is {}",
provider.getClass().getName(), left.getClass().getName(), right.getClass().getName());
}
return null;
}
@Override
public BaggageContext deserialize(byte[] serialized, int offset, int length) {
return provider.deserialize(serialized, offset, length);
}
@Override
public BaggageContext deserialize(ByteBuffer buf) {
return provider.deserialize(buf);
}
@Override
public byte[] serialize(BaggageContext baggage) {
if (provider.isValid(baggage)) {
return provider.serialize((B) baggage);
} else {
log.warn("discarding incompatible baggage to {}.serialize; baggage class is {}",
provider.getClass().getName(), baggage.getClass().getName());
}
return null;
}
@Override
public byte[] serialize(BaggageContext baggage, int maximumSerializedSize) {
if (provider.isValid(baggage)) {
return provider.serialize((B) baggage, maximumSerializedSize);
} else {
log.warn("discarding incompatible baggage to {}.serialize; baggage class is {}",
provider.getClass().getName(), baggage.getClass().getName());
}
return null;
}
}
package brown.tracingplane;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.typesafe.config.ConfigException;
import com.typesafe.config.ConfigFactory;
import brown.tracingplane.noopprovider.NoOpBaggageContextProvider;
/**
* <p>
* Loads the default configured {@link BaggageProvider} using reflection. Checks the <code>baggage.provider</code>
* property.
* </p>
*/
public class DefaultBaggageProvider {
private static final Logger log = LoggerFactory.getLogger(DefaultBaggageProvider.class);
/** Not instantiable */
private DefaultBaggageProvider() {}
private static boolean initialized = false;
private static BaggageProvider<? extends BaggageContext> instance = null;
@SuppressWarnings("unchecked")
private static synchronized void initialize() {
if (initialized) {
return;
}
try {
String providerClass = ConfigFactory.load().getString("baggage.provider");
try {
instance = (BaggageProvider<? extends BaggageContext>) Class.forName(providerClass).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
log.error("Unable to instantiate baggage.provider " + providerClass, e);
}
} catch (ConfigException.Missing e) {
log.error("No baggage.provider has been configured");
} catch (ConfigException.WrongType e) {
log.error("Invalid value (expected a string) for baggage.provider " +
ConfigFactory.load().getAnyRef("baggage.provider"));
} finally {
initialized = true;
if (instance == null) {
instance = new NoOpBaggageContextProvider();
}
}
}
/**
* @return the configured {@link BaggageProvider} instance. The default baggage provider can be set using
* -Dbaggage.provider. If no instance has been configured, this method will return a
* {@link NoOpBaggageContextProvider}.
*/
public static BaggageProvider<? extends BaggageContext> get() {
if (!initialized) {
initialize();
}
return instance;
}
/**
* @return the configured {@link BaggageProvider} instance, wrapped with a {@link BaggageProviderProxy}. The default
* baggage provider can be set using -Dbaggage.provider. If no instance has been configured, this method
* will return a {@link NoOpBaggageContextProvider}.
*/
public static BaggageProvider<BaggageContext> getWrapped() {
BaggageProvider<? extends BaggageContext> provider = get();
if (provider instanceof NoOpBaggageContextProvider) {
return (NoOpBaggageContextProvider) provider;
} else {
return BaggageProviderProxy.wrap(provider);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment