KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > tm > recovery > BatchRecoveryLogger


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.tm.recovery;
23
24 import java.io.File JavaDoc;
25 import java.nio.ByteBuffer JavaDoc;
26 import java.util.ArrayList JavaDoc;
27
28 import javax.transaction.xa.Xid JavaDoc;
29
30 import org.jboss.tm.XidFactoryBase;
31
32 /**
33  * This <code>RecoveryLogger</code> implementation
34  * uses <code>BatchWriter</code>s that batch log write requests
35  * in order to minimize disk forcing activity. A
36  * <code>BatchRecoveryLogger</code> instance is the "main object" of the
37  * the recovery logger service, which is simply an MBean wrapper for that
38  * instance.
39  *
40  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
41  * @author <a HREF="mailto:reverbel@ime.usp.br">Francisco Reverbel</a>
42  * @version $Revision: 37459 $
43  */

44 public class BatchRecoveryLogger
45       implements RecoveryLogger
46 {
47    /** Array of names of directories that contain recovery log files. */
48    private String JavaDoc[] stringDirectoryList;
49    
50    /** Array of directories that contain recovery log files. */
51    private File JavaDoc[] directoryList;
52    
53    /** The constant size of a recovery log file. */
54    private int logFileSize;
55    
56    /** Array of recovery log files found at recovery time. */
57    private File JavaDoc[] existingRecoveryLogFiles;
58    
59    /** Array of log writers (one per directory that contains log files). */
60    private BatchWriter[] writers;
61    
62    /** Number of log writers (number of directories that contain log files). */
63    private int numWriters;
64    
65    /** Sequential number used to choose a log writer */
66    private volatile int seqNo = 0;
67    
68    /** Name of the directory that contains heuristic status log files. */
69    private String JavaDoc heuristicStatusLogDirectoryName;
70    
71    /** Directory that contain heuristic status log files. */
72    private File JavaDoc heuristicStatusLogDirectory;
73    
74    /** Array of heuristic status log files found at recovery time. */
75    private File JavaDoc[] existingHeuristicStatusLogFiles;
76    
77    /** Heuristic status log writer. */
78    private HeuristicStatusLog heuristicStatusLogger;
79    
80    /** The server's Xid factory. */
81    private XidFactoryBase xidFactory;
82
83    /** For asynchronously restarting <code>BatchLog</code> instances. */
84    private LogRestarter logCleaner;
85    
86    // Package protected methods -------------------------------------
87
// (The BatchRecoveryLoggerService calls these methods.)
88

89    /*
90     * Gets the names of directories that contain recovery log files.
91     *
92     * @return an array of names of directories that contain recovery log
93     * files.
94     *
95     */

96    String JavaDoc[] getDirectoryList()
97    {
98       return stringDirectoryList;
99    }
100
101    /**
102     * Sets the names of directories that contain recovery log files.
103     * <p />
104     * This method used to be package protected. It was changed to public just
105     * for testing purposes.
106     *
107     * @param directoryList array of names of directories that contain recovery
108     * log files.
109     *
110     */

111    public void setDirectoryList(String JavaDoc[] directoryList)
112    {
113       this.stringDirectoryList = directoryList;
114       File JavaDoc[] list = new File JavaDoc[directoryList.length];
115       for (int i = 0; i < directoryList.length; i++)
116       {
117          list[i] = new File JavaDoc(directoryList[i]);
118          list[i] = list[i].getAbsoluteFile();
119          if (!list[i].exists())
120          {
121             if (!list[i].mkdirs())
122             {
123                throw new RuntimeException JavaDoc("Unable to create recovery directory: "
124                                           + directoryList[i]);
125             }
126          }
127       }
128       this.directoryList = list;
129    }
130
131    /**
132     * Gets the constant size of a log file.
133     *
134     * @return the constans size of a log file, in bytes.
135     */

136    int getLogFileSize()
137    {
138       return logFileSize;
139    }
140
141    /**
142     * Sets the constant size of a log file.
143     * <p />
144     * This method used to be package protected. It was changed to public just
145     * for testing purposes.
146     *
147     * @param logFileSize the constant size of a log file, in bytes.
148     */

149    public void setLogFileSize(int logFileSize)
150    {
151       this.logFileSize = logFileSize;
152    }
153    
154    /**
155     * Gets the name of the directory that contains heuristic status log files.
156     *
157     * @return the name of the directory that contains heuristic status log
158     * files.
159     */

160    String JavaDoc getHeuristicStatusLogDirectory()
161    {
162       return heuristicStatusLogDirectoryName;
163    }
164
165    /**
166     * Sets the name of the directory that contains heuristic status log files.
167     * <p />
168     * This method used to be package protected. It was changed to public just
169     * for testing purposes.
170     *
171     * @param heuristicStatusLogDirectoryName the name of the directory that
172     * contains heuristic status log files.
173     */

174    public void setHeuristicStatusLogDirectory(String JavaDoc heuristicStatusLogDirectoryName)
175    {
176       this.heuristicStatusLogDirectoryName = heuristicStatusLogDirectoryName;
177       heuristicStatusLogDirectory = new File JavaDoc(heuristicStatusLogDirectoryName);
178       heuristicStatusLogDirectory =
179          heuristicStatusLogDirectory.getAbsoluteFile();
180       if (!heuristicStatusLogDirectory.exists())
181       {
182          if (!heuristicStatusLogDirectory.mkdirs())
183          {
184             throw new RuntimeException JavaDoc("Unable to create heuristic status " +
185                                        "log directory: "
186                                        + heuristicStatusLogDirectoryName);
187          }
188       }
189    }
190
191    /**
192     * Gets the Xid factory.
193     *
194     * @return the Xid factory.
195     */

196    XidFactoryBase getXidFactory()
197    {
198       return xidFactory;
199    }
200    
201    /**
202     * Sets the Xid factory
203     * <p />
204     * This method used to be package protected. It was changed to public just
205     * for testing purposes.
206     *
207     * @param xidFactory the Xid factory.
208     */

209    public void setXidFactory(XidFactoryBase xidFactory)
210    {
211       this.xidFactory = xidFactory;
212    }
213
214    /**
215     * Starts this <code>BatchRecoveryLoggger</code>.
216     * <p />
217     * This method used to be package protected. It was changed to public just
218     * for testing purposes.
219     */

220    public void start() throws Exception JavaDoc
221    {
222       ArrayList JavaDoc list = new ArrayList JavaDoc();
223       for (int i = 0; i < directoryList.length; i++)
224       {
225          File JavaDoc dir = directoryList[i];
226          File JavaDoc[] files = dir.listFiles();
227          for (int j = 0; j < files.length; j++)
228          {
229             list.add(files[j]);
230          }
231       }
232       existingRecoveryLogFiles = (File JavaDoc[]) list.toArray(new File JavaDoc[list.size()]);
233
234       logCleaner = new LogRestarter();
235       new Thread JavaDoc(logCleaner, "Log file cleaner").start();
236
237       writers = new BatchWriter[directoryList.length];
238       String JavaDoc branchQualifier = xidFactory.getBranchQualifier();
239       for (int i = 0; i < directoryList.length; i++)
240       {
241          writers[i] = new BatchWriter(branchQualifier, logFileSize / 128,
242                                    directoryList[i], logFileSize, logCleaner);
243          new Thread JavaDoc(writers[i], "Batch Recovery Log " + i).start();
244       }
245       numWriters = writers.length;
246       
247       existingHeuristicStatusLogFiles = heuristicStatusLogDirectory.listFiles();
248       heuristicStatusLogger =
249          new HeuristicStatusLog(heuristicStatusLogDirectory);
250    }
251
252    /**
253     * Stops this <code>BatchRecoveryLoggger</code>.
254     * <p />
255     * This method used to be package protected. It was changed to public just
256     * for testing purposes.
257     */

258    public void stop() throws Exception JavaDoc
259    {
260       for (int i = 0; i < writers.length; i++)
261       {
262          writers[i].stop();
263       }
264       logCleaner.stop();
265       heuristicStatusLogger.close();
266    }
267
268    // RecoveryLogger implementation ---------------------------------
269

270   /**
271    * @see org.jboss.tm.recovery.RecoveryLogger#saveCommitDecision(
272    * long, java.lang.String[])
273    */

274    public TxCompletionHandler saveCommitDecision(long localTransactionId,
275                                                  String JavaDoc[] resources)
276    {
277       ByteBuffer JavaDoc buffer;
278       
279       if (resources == null || resources.length == 0)
280       {
281          buffer = LogRecord.createTxCommittedRecord(localTransactionId);
282          return writers[++seqNo % numWriters].addBatch(buffer, false);
283       }
284       else
285       {
286          buffer = LogRecord.createTxCommittedRecord(localTransactionId,
287                                                     resources);
288          return writers[++seqNo % numWriters].addBatch(buffer, true);
289       }
290    }
291
292    /**
293     * @see org.jboss.tm.recovery.RecoveryLogger#savePrepareDecision(
294     * long, int, byte[], java.lang.String, java.lang.String[])
295     */

296    public TxCompletionHandler savePrepareDecision(long localTransactionId,
297                                                   int inboundFormatId,
298                                                   byte[] globalTransactionId,
299                                                   String JavaDoc recoveryCoordinator,
300                                                   String JavaDoc[] resources)
301    {
302       ByteBuffer JavaDoc buffer = LogRecord.createTxPreparedRecord(localTransactionId,
303                                                            inboundFormatId,
304                                                            globalTransactionId,
305                                                            recoveryCoordinator,
306                                                            resources);
307       return writers[++seqNo % numWriters].addBatch(buffer, true);
308    }
309    
310    /**
311     * @see org.jboss.tm.recovery.RecoveryLogger#savePrepareDecision(
312     * long, javax.transaction.xa.Xid, java.lang.String[])
313     */

314    public TxCompletionHandler savePrepareDecision(long localTransactionId,
315                                                   Xid JavaDoc inboundXid,
316                                                   String JavaDoc[] resources)
317    {
318       ByteBuffer JavaDoc buffer =
319          LogRecord.createJcaTxPreparedRecord(localTransactionId,
320                                             inboundXid,
321                                             resources);
322       return writers[++seqNo % numWriters].addBatch(buffer, true);
323    }
324
325    /**
326     * @see org.jboss.tm.recovery.RecoveryLogger#saveHeuristicStatus(
327     * long, boolean, int, byte[], byte[], int, int, boolean int[],
328     * org.jboss.tm.recovery.HeuristicStatus[])
329     */

330    public void saveHeuristicStatus(long localTransactionId,
331                                    boolean foreignTx,
332                                    int formatId,
333                                    byte[] globalTransactionId,
334                                    byte[] inboundBranchQualifier,
335                                    int transactionStatus,
336                                    int heurStatusCode,
337                                    boolean locallyDetectedHeuristicHazard,
338                                    int[] xaResourceHeuristics,
339                                    HeuristicStatus[] remoteResourceHeuristics)
340    {
341       ByteBuffer JavaDoc buffer =
342          LogRecord.createHeurStatusRecord(localTransactionId,
343                                          foreignTx,
344                                          formatId,
345                                          globalTransactionId,
346                                          inboundBranchQualifier,
347                                          transactionStatus,
348                                          heurStatusCode,
349                                          locallyDetectedHeuristicHazard,
350                                          xaResourceHeuristics,
351                                          remoteResourceHeuristics);
352       heuristicStatusLogger.write(buffer);
353    }
354
355    /**
356     * @see org.jboss.tm.recovery.RecoveryLogger#clearHeuristicStatus(long)
357     */

358    public void clearHeuristicStatus(long localTransactionId)
359    {
360       ByteBuffer JavaDoc buffer =
361          LogRecord.createHeurForgottenRecord(localTransactionId);
362       heuristicStatusLogger.write(buffer);
363    }
364    
365    /**
366     * @see org.jboss.tm.recovery.RecoveryLogger#getRecoveryLogs()
367     */

368    public RecoveryLogReader[] getRecoveryLogs()
369    {
370       if (existingRecoveryLogFiles == null
371             || existingRecoveryLogFiles.length == 0)
372          return null;
373
374       RecoveryLogReader[] readers =
375          new RecoveryLogReader[existingRecoveryLogFiles.length];
376       for (int i = 0; i < readers.length; i++)
377       {
378          readers[i] =
379             new BatchRecoveryLogReader(existingRecoveryLogFiles[i], xidFactory);
380       }
381       return readers;
382    }
383
384    /**
385     * @see org.jboss.tm.recovery.RecoveryLogger#getHeuristicStatusLogs()
386     */

387    public HeuristicStatusLogReader[] getHeuristicStatusLogs()
388    {
389       if (existingHeuristicStatusLogFiles == null
390             || existingHeuristicStatusLogFiles.length == 0)
391          return null;
392
393       HeuristicStatusLogReader[] readers =
394          new HeuristicStatusLogReader[existingHeuristicStatusLogFiles.length];
395       for (int i = 0; i < readers.length; i++)
396       {
397          readers[i] = new SimpleHeuristicStatusLogReader(
398                                           existingHeuristicStatusLogFiles[i]);
399       }
400       return readers;
401    }
402
403 }
404
Popular Tags