001: /* RecyclingSerialBinding
002: *
003: * $Id: RecyclingSerialBinding.java 4667 2006-09-26 20:38:48Z paul_jack $
004: *
005: * Created on May 25, 2005
006: *
007: * Copyright (C) 2005 Internet Archive.
008: *
009: * This file is part of the Heritrix web crawler (crawler.archive.org).
010: *
011: * Heritrix is free software; you can redistribute it and/or modify
012: * it under the terms of the GNU Lesser Public License as published by
013: * the Free Software Foundation; either version 2.1 of the License, or
014: * any later version.
015: *
016: * Heritrix is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019: * GNU Lesser Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser Public License
022: * along with Heritrix; if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: */
025: package org.archive.crawler.frontier;
026:
027: import java.io.IOException;
028:
029: import com.sleepycat.bind.serial.ClassCatalog;
030: import com.sleepycat.bind.serial.SerialBinding;
031: import com.sleepycat.bind.serial.SerialOutput;
032: import com.sleepycat.je.DatabaseEntry;
033: import com.sleepycat.util.FastOutputStream;
034: import com.sleepycat.util.RuntimeExceptionWrapper;
035:
036: /**
037: * A SerialBinding that recycles a single FastOutputStream per
038: * thread, avoiding reallocation of the internal buffer for
039: * either repeated serializations or because of mid-serialization
040: * expansions. (Cached stream's buffer will quickly grow to a size
041: * sufficient for all serialized instances.)
042: *
043: * @author gojomo
044: */
045: public class RecyclingSerialBinding extends SerialBinding {
046: /**
047: * Thread-local cache of reusable FastOutputStream
048: */
049: ThreadLocal<FastOutputStream> fastOutputStreamHolder = new ThreadLocal<FastOutputStream>();
050:
051: private ClassCatalog classCatalog;
052: private Class baseClass;
053:
054: /**
055: * Constructor. Save parameters locally, as superclass
056: * fields are private.
057: *
058: * @param classCatalog is the catalog to hold shared class information
059: *
060: * @param baseClass is the base class for serialized objects stored using
061: * this binding
062: */
063: public RecyclingSerialBinding(ClassCatalog classCatalog,
064: Class baseClass) {
065: super (classCatalog, baseClass);
066: this .classCatalog = classCatalog;
067: this .baseClass = baseClass;
068: }
069:
070: /**
071: * Copies superclass simply to allow different source for FastOoutputStream.
072: *
073: * @see com.sleepycat.bind.serial.SerialBinding#entryToObject
074: */
075: public void objectToEntry(Object object, DatabaseEntry entry) {
076:
077: if (baseClass != null && !baseClass.isInstance(object)) {
078: throw new IllegalArgumentException("Data object class ("
079: + object.getClass()
080: + ") not an instance of binding's base class ("
081: + baseClass + ')');
082: }
083: FastOutputStream fo = getFastOutputStream();
084: try {
085: SerialOutput jos = new SerialOutput(fo, classCatalog);
086: jos.writeObject(object);
087: } catch (IOException e) {
088: throw new RuntimeExceptionWrapper(e);
089: }
090:
091: byte[] hdr = SerialOutput.getStreamHeader();
092: entry.setData(fo.getBufferBytes(), hdr.length, fo
093: .getBufferLength()
094: - hdr.length);
095: }
096:
097: /**
098: * Get the cached (and likely pre-grown to efficient size) FastOutputStream,
099: * creating it if necessary.
100: *
101: * @return FastOutputStream
102: */
103: private FastOutputStream getFastOutputStream() {
104: FastOutputStream fo = (FastOutputStream) fastOutputStreamHolder
105: .get();
106: if (fo == null) {
107: fo = new FastOutputStream();
108: fastOutputStreamHolder.set(fo);
109: }
110: fo.reset();
111: return fo;
112: }
113: }
|