Skip to content

Commit 0e685f9

Browse files
committed
Merge branch 'release/0.3.3'
2 parents df4574d + 7a45300 commit 0e685f9

File tree

9 files changed

+104
-20
lines changed

9 files changed

+104
-20
lines changed

CHANGES.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# chill #
22

3+
### 0.3.3
4+
* Serialize synthetic fields by default: https://github.com/twitter/chill/pull/135
5+
* Prefer Java to Kryo, but check both in Externalizer: https://github.com/twitter/chill/pull/138
6+
37
### 0.3.2
48

59
* Add a LocaleSerializer to chill-java: https://github.com/twitter/chill/pull/128

chill-java/src/main/java/com/twitter/chill/config/ConfiguredInstantiator.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ public static void setSerialized(Config conf, Class<? extends KryoInstantiator>
131131
KryoInstantiator refki = reflect(reflector, conf);
132132
String kistr = serialize(refki.newKryo(), ki);
133133
// Verify, that deserialization works:
134-
deserialize(refki.newKryo(), kistr); // ignore the result, just see if it throws
134+
KryoInstantiator deser = deserialize(refki.newKryo(), kistr); // ignore the result, just see if it throws
135+
deser.newKryo(); // just see if we can still create it
135136
conf.set(KEY, reflector.getName() + ":" + kistr);
136137
}
137138

chill-java/src/test/scala/com/twitter/chill/config/ConfiguredInstantiatorTest.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ package com.twitter.chill.config
1919
import org.specs._
2020

2121
import com.twitter.chill._
22+
import com.esotericsoftware.kryo.Kryo
2223

23-
class TestInst extends KryoInstantiator { override def newKryo = sys.error("blow up") }
24+
class TestInst extends KryoInstantiator { override def newKryo = new Kryo }
2425

2526
class ReflectingInstantiatorTest extends Specification {
2627
"A ConfiguredInstantiator" should {

chill-scala/src/main/scala/com/twitter/chill/Externalizer.scala

+53-11
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,15 @@ limitations under the License.
1515
*/
1616
package com.twitter.chill
1717

18-
import _root_.java.io.{ByteArrayOutputStream, Externalizable, ObjectInput, ObjectOutput}
18+
import _root_.java.io.{
19+
ByteArrayOutputStream,
20+
ByteArrayInputStream,
21+
Externalizable,
22+
ObjectInput,
23+
ObjectOutput,
24+
ObjectInputStream,
25+
ObjectOutputStream
26+
}
1927

2028
object Externalizer {
2129
def apply[T](t: T): Externalizer[T] = {
@@ -64,6 +72,28 @@ class Externalizer[T] extends Externalizable {
6472
// 1 here is 1 thread, since we will likely only serialize once
6573
private val kpool = KryoPool.withByteArrayOutputStream(1, kryo)
6674

75+
/** Try to round-trip and see if it works without error
76+
*/
77+
lazy val javaWorks: Boolean = {
78+
try {
79+
val baos = new ByteArrayOutputStream()
80+
val oos = new ObjectOutputStream(baos)
81+
oos.writeObject(item)
82+
val bytes = baos.toByteArray
83+
val testInput = new ByteArrayInputStream(bytes)
84+
val ois = new ObjectInputStream(testInput)
85+
ois.readObject // this may throw
86+
true
87+
}
88+
catch {
89+
case t: Throwable =>
90+
Option(System.getenv.get("CHILL_EXTERNALIZER_DEBUG"))
91+
.filter(_.toBoolean)
92+
.foreach { _ => t.printStackTrace }
93+
false
94+
}
95+
}
96+
6797
private def safeToBytes: Option[Array[Byte]] = {
6898
try {
6999
val bytes = kpool.toBytesWithClass(item)
@@ -84,24 +114,36 @@ class Externalizer[T] extends Externalizable {
84114

85115
def readExternal(in: ObjectInput) {
86116
in.read match {
117+
case JAVA =>
118+
item = in.readObject.asInstanceOf[Option[T]]
87119
case KRYO =>
88120
val sz = in.readInt
89121
val buf = new Array[Byte](sz)
90122
in.readFully(buf)
91123
item = fromBytes(buf)
92-
case JAVA =>
93-
item = in.readObject.asInstanceOf[Option[T]]
94124
}
95125
}
126+
127+
protected def writeJava(out: ObjectOutput): Boolean =
128+
javaWorks && {
129+
out.write(JAVA)
130+
out.writeObject(item)
131+
true
132+
}
133+
134+
protected def writeKryo(out: ObjectOutput): Boolean =
135+
safeToBytes.map { bytes =>
136+
out.write(KRYO)
137+
out.writeInt(bytes.size)
138+
out.write(bytes)
139+
true
140+
}.getOrElse(false)
141+
96142
def writeExternal(out: ObjectOutput) {
97-
safeToBytes match {
98-
case Some(bytes) =>
99-
out.write(KRYO)
100-
out.writeInt(bytes.size)
101-
out.write(bytes)
102-
case None =>
103-
out.write(JAVA)
104-
out.writeObject(item)
143+
writeJava(out) || writeKryo(out) || {
144+
val inner = item.get
145+
sys.error("Neither Java nor Kyro works for class: %s instance: %s\nexport CHILL_EXTERNALIZER_DEBUG=true to see both stack traces"
146+
.format(inner.getClass, inner))
105147
}
106148
}
107149
}

chill-scala/src/main/scala/com/twitter/chill/KryoBase.scala

+4-3
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ class KryoBase extends Kryo {
4949
super.newDefaultSerializer(klass) match {
5050
case fs: FieldSerializer[_] =>
5151
//Scala has a lot of synthetic fields that must be serialized:
52-
if(classOf[scala.Serializable].isAssignableFrom(klass)) {
53-
fs.setIgnoreSyntheticFields(false)
54-
}
52+
//We also enable it by default in java since not wanting these fields
53+
//serialized looks like the exception rather than the rule.
54+
fs.setIgnoreSyntheticFields(false)
55+
5556
/**
5657
* This breaks scalding, but something like this should be used when
5758
* working with the repl.

chill-scala/src/test/scala/com/twitter/chill/KryoSpec.scala

+19
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ case class TestValMap(map: Map[String,Double])
3636
case class TestValHashMap(map: HashMap[String,Double])
3737
case class TestVarArgs(vargs: String*)
3838

39+
class SomeRandom(val x: Int)
40+
3941
object WeekDay extends Enumeration {
4042
type WeekDay = Value
4143
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
4244
}
4345

46+
trait ExampleUsingSelf { self =>
47+
def count = 0
48+
def addOne = new ExampleUsingSelf {override def count=self.count+1}
49+
}
50+
4451
class KryoSpec extends Specification with BaseProperties {
4552

4653
noDetailedDiffs() //Fixes issue for scala 2.9
@@ -84,6 +91,11 @@ class KryoSpec extends Specification with BaseProperties {
8491
serdeser must be_==(orig)
8592
}
8693
}
94+
"handle trait with reference of self" in {
95+
var a= new ExampleUsingSelf{}
96+
var b=rt(a.addOne)
97+
b.count must be_==(1)
98+
}
8799
"handle manifests" in {
88100
rt(manifest[Int]) must be_==(manifest[Int])
89101
rt(manifest[(Int,Int)]) must be_==(manifest[(Int,Int)])
@@ -142,8 +154,15 @@ class KryoSpec extends Specification with BaseProperties {
142154
"work with Externalizer" in {
143155
val l = List(1,2,3)
144156
val ext = Externalizer(l)
157+
ext.javaWorks must be_==(true)
145158
jrt(ext).get must_==(l)
146159
}
160+
"work with Externalizer with non-java-ser" in {
161+
val l = new SomeRandom(3)
162+
val ext = Externalizer(l)
163+
ext.javaWorks must be_==(false)
164+
jrt(ext).get.x must_==(l.x)
165+
}
147166
"handle Regex" in {
148167
val test = """\bhilarious""".r
149168
val roundtripped = rt(test)

chill-scala/src/test/scala/com/twitter/chill/config/ReflectingInstantiatorTest.scala

+18
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,23 @@ class ReflectingInstantiatorTest extends Specification {
6464
ri.equals(ri2) must be_==(true)
6565
ri2.equals(ri) must be_==(true)
6666
}
67+
68+
"be serialized when added onto a ConfiguredInstantiator" in {
69+
val conf = new JavaMapConfig
70+
ConfiguredInstantiator.setReflect(conf, classOf[ScalaKryoInstantiator])
71+
val instantiator = new ConfiguredInstantiator(conf).getDelegate()
72+
.withRegistrar {
73+
new ReflectingDefaultRegistrar(classOf[List[_]], classOf[com.esotericsoftware.kryo.serializers.JavaSerializer])
74+
}
75+
try {
76+
ConfiguredInstantiator.setSerialized(
77+
conf,
78+
classOf[ScalaKryoInstantiator],
79+
instantiator
80+
)
81+
}catch{
82+
case e => fail("Got exception serializing the instantiator\n" + e.printStackTrace)
83+
}
84+
}
6785
}
6886
}

project/Build.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ object ChillBuild extends Build {
1212

1313
val sharedSettings = Project.defaultSettings ++ mimaDefaultSettings ++ Seq(
1414

15-
version := "0.3.2",
15+
version := "0.3.3",
1616
organization := "com.twitter",
1717
scalaVersion := "2.9.3",
1818
crossScalaVersions := Seq("2.9.3", "2.10.0"),
@@ -103,7 +103,7 @@ object ChillBuild extends Build {
103103
.filterNot(unreleasedModules.contains(_))
104104
.map { s =>
105105
val suffix = if (javaOnly.contains(s)) "" else "_2.9.3"
106-
"com.twitter" % ("chill-" + s + suffix) % "0.3.1"
106+
"com.twitter" % ("chill-" + s + suffix) % "0.3.2"
107107
}
108108

109109
def module(name: String) = {

project/plugins.sbt

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
resolvers += Resolver.url("sbt-plugin-releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases/"))(Resolver.ivyStylePatterns)
22

3-
addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.7")
4-
53
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.5")

0 commit comments

Comments
 (0)