1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.archive.crawler.frontier;
26
27 import java.io.IOException;
28
29 import com.sleepycat.bind.serial.ClassCatalog;
30 import com.sleepycat.bind.serial.SerialBinding;
31 import com.sleepycat.bind.serial.SerialOutput;
32 import com.sleepycat.je.DatabaseEntry;
33 import com.sleepycat.util.FastOutputStream;
34 import com.sleepycat.util.RuntimeExceptionWrapper;
35
36 /***
37 * A SerialBinding that recycles a single FastOutputStream per
38 * thread, avoiding reallocation of the internal buffer for
39 * either repeated serializations or because of mid-serialization
40 * expansions. (Cached stream's buffer will quickly grow to a size
41 * sufficient for all serialized instances.)
42 *
43 * @author gojomo
44 */
45 public class RecyclingSerialBinding extends SerialBinding {
46 /***
47 * Thread-local cache of reusable FastOutputStream
48 */
49 ThreadLocal<FastOutputStream> fastOutputStreamHolder
50 = new ThreadLocal<FastOutputStream>();
51
52 private ClassCatalog classCatalog;
53 private Class baseClass;
54
55 /***
56 * Constructor. Save parameters locally, as superclass
57 * fields are private.
58 *
59 * @param classCatalog is the catalog to hold shared class information
60 *
61 * @param baseClass is the base class for serialized objects stored using
62 * this binding
63 */
64 public RecyclingSerialBinding(ClassCatalog classCatalog, Class baseClass) {
65 super(classCatalog, baseClass);
66 this.classCatalog = classCatalog;
67 this.baseClass = baseClass;
68 }
69
70 /***
71 * Copies superclass simply to allow different source for FastOoutputStream.
72 *
73 * @see com.sleepycat.bind.serial.SerialBinding#entryToObject
74 */
75 public void objectToEntry(Object object, DatabaseEntry entry) {
76
77 if (baseClass != null && !baseClass.isInstance(object)) {
78 throw new IllegalArgumentException(
79 "Data object class (" + object.getClass() +
80 ") not an instance of binding's base class (" +
81 baseClass + ')');
82 }
83 FastOutputStream fo = getFastOutputStream();
84 try {
85 SerialOutput jos = new SerialOutput(fo, classCatalog);
86 jos.writeObject(object);
87 } catch (IOException e) {
88 throw new RuntimeExceptionWrapper(e);
89 }
90
91 byte[] hdr = SerialOutput.getStreamHeader();
92 entry.setData(fo.getBufferBytes(), hdr.length,
93 fo.getBufferLength() - hdr.length);
94 }
95
96 /***
97 * Get the cached (and likely pre-grown to efficient size) FastOutputStream,
98 * creating it if necessary.
99 *
100 * @return FastOutputStream
101 */
102 private FastOutputStream getFastOutputStream() {
103 FastOutputStream fo = (FastOutputStream) fastOutputStreamHolder.get();
104 if (fo == null) {
105 fo = new FastOutputStream();
106 fastOutputStreamHolder.set(fo);
107 }
108 fo.reset();
109 return fo;
110 }
111 }