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 }