View Javadoc

    1   /***
    2    *
    3    * Copyright 2004 Protique Ltd
    4    *
    5    * Licensed under the Apache License, Version 2.0 (the "License");
    6    * you may not use this file except in compliance with the License.
    7    * You may obtain a copy of the License at
    8    *
    9    * http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   **/
    18
    19  package org.codehaus.activemq.message.util;
    20  import java.io.File;
    21  import java.io.FileFilter;
    22  import java.io.IOException;
    23  import org.apache.commons.logging.Log;
    24  import org.apache.commons.logging.LogFactory;
    25  import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
    26
    27  /***
    28   * A DataContainer handles file persistence for a DiskBoundedQueue
    29   * The DataContainer is a temporary data structure, that is only
    30   * designed to exist for the lifetime of the application
    31   *
    32   * @version $Revision: 1.1 $
    33   */
    34  class DataContainer {
    35      private CopyOnWriteArrayList dataBlocks = new CopyOnWriteArrayList();
    36      private FileDataBlock writeBlock;
    37      private FileDataBlock readBlock;
    38      private File dir;
    39      private long length;
    40      private int size;
    41      private String name;
    42      private int maxBlockSize;
    43      private int sequence;
    44      private static final String SUFFIX = ".fdb";
    45      private static final Log log = LogFactory.getLog(DataContainer.class);
    46
    47      /***
    48       * Constructor for the data container
    49       *
    50       * @param dir directory where to create the data blocks
    51       * @param name for the data block names
    52       * @param maxBlockSize maximum size (in bytes) of the data blocks
    53       * @throws IOException
    54       */
    55      DataContainer(File dir, String name, int maxBlockSize) throws IOException {
    56          this.dir = dir;
    57          this.name = name;
    58          this.maxBlockSize = maxBlockSize;
    59      }
    60
    61      /***
    62       * Delete all previous files of the same suffix in the directory
    63       */
    64      void deleteAll() {
    65          FileFilter filter = new FileFilter() {
    66              public boolean accept(File file) {
    67                  return (file.getName().endsWith(SUFFIX) && file.getName().startsWith(name));
    68              }
    69          };
    70          File[] files = dir.listFiles(filter);
    71          if (files != null) {
    72              for (int i = 0;i < files.length;i++) {
    73                  files[i].delete();
    74              }
    75          }
    76      }
    77
    78
    79
    80      /***
    81       * @return true if this DataContainer is empty
    82       */
    83      public synchronized boolean isEmpty() {
    84          return size == 0;
    85      }
    86
    87      /***
    88       * @return the length (in bytes) of unread data in the DataContainer
    89       */
    90      public long length() {
    91          return length;
    92      }
    93
    94      /***
    95       * @return the number of data entries unread
    96       */
    97      public int size() {
    98          return size;
    99      }
    100
    101     /***
    102      * write a block of data into the Container
    103      *
    104      * @param data
    105      * @throws IOException
    106      */
    107     public synchronized void write(byte[] data) throws IOException {
    108         if (writeBlock == null) {
    109             writeBlock = createDataBlock(sequence++);
    110             dataBlocks.add(writeBlock);
    111             readBlock = writeBlock;
    112         }
    113         else if (!writeBlock.isEnoughSpace(data)) {
    114             writeBlock = createDataBlock(sequence++);
    115             dataBlocks.add(writeBlock);
    116         }
    117         length += data.length;
    118         size++;
    119         writeBlock.write(data);
    120     }
    121
    122     /***
    123      * read a block of data from the container
    124      *
    125      * @return next data entry to read
    126      * @throws IOException
    127      */
    128     public byte[] read() throws IOException {
    129         byte[] result = null;
    130         if (readBlock != null) {
    131             result = readBlock.read();
    132             if (result == null) {
    133                 if (readBlock != writeBlock) {
    134                     readBlock.close();
    135                     dataBlocks.remove(readBlock);
    136                     readBlock = (FileDataBlock) dataBlocks.get(0);
    137                 }
    138             }
    139             else {
    140                 length -= result.length;
    141                 size--;
    142             }
    143         }
    144         return result;
    145     }
    146
    147     /***
    148      * close the DataContainer and corresponding FileDataBlocks
    149      *
    150      * @throws IOException
    151      */
    152     public void close() throws IOException {
    153         for (int i = 0;i < dataBlocks.size();i++) {
    154             FileDataBlock db = (FileDataBlock) dataBlocks.get(i);
    155             db.close();
    156         }
    157         dataBlocks.clear();
    158         readBlock = null;
    159         writeBlock = null;
    160         size = 0;
    161         length = 0l;
    162     }
    163
    164     /***
    165      * create a FileDataBlock
    166      *
    167      * @param sequence
    168      * @return a new FileDataBlock
    169      * @throws IOException
    170      */
    171     private FileDataBlock createDataBlock(int sequence) throws IOException {
    172         String fileName = name + "_" + sequence + SUFFIX;
    173         //File file = new File(dir, fileName);
    174         File file = File.createTempFile(name, SUFFIX, dir);
    175         file.deleteOnExit();
    176         return new FileDataBlock(file, maxBlockSize);
    177     }
    178 }