View Javadoc

    1   /* RecyclingSerialBinding
    2   *
    3   * $Id: RecyclingSerialBinding.java 4667 2006-09-26 20:38:48Z paul_jack $
    4   *
    5   * Created on May 25, 2005
    6   *
    7   * Copyright (C) 2005 Internet Archive.
    8   *
    9   * This file is part of the Heritrix web crawler (crawler.archive.org).
    10  *
    11  * Heritrix is free software; you can redistribute it and/or modify
    12  * it under the terms of the GNU Lesser Public License as published by
    13  * the Free Software Foundation; either version 2.1 of the License, or
    14  * any later version.
    15  *
    16  * Heritrix is distributed in the hope that it will be useful,
    17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19  * GNU Lesser Public License for more details.
    20  *
    21  * You should have received a copy of the GNU Lesser Public License
    22  * along with Heritrix; if not, write to the Free Software
    23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    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 }