View Javadoc
1   //******************************************************************************
2   //
3   // File:    BackendFileWriter.java
4   // Package: edu.rit.pj.cluster
5   // Unit:    Class edu.rit.pj.cluster.BackendFileWriter
6   //
7   // This Java source file is copyright (C) 2006 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.pj.cluster;
41  
42  import java.io.File;
43  import java.io.IOException;
44  import java.io.PrintStream;
45  import java.util.HashMap;
46  import java.util.Map;
47  
48  import edu.rit.io.LineBufferedOutputStream;
49  
50  /**
51   * Class BackendFileWriter provides an object that writes sequential files in
52   * the job backend process.
53   * <P>
54   * <I>Note:</I> Class BackendFileWriter is not multiple thread safe; it assumes
55   * it is being called by a synchronized method in the job backend.
56   *
57   * @author Alan Kaminsky
58   * @version 05-Nov-2006
59   */
60  public class BackendFileWriter {
61  
62  // Exported data members.
63      /**
64       * Print stream for printing on the job frontend's standard output.
65       */
66      public final PrintStream out;
67  
68      /**
69       * Print stream for printing on the job frontend's standard error.
70       */
71      public final PrintStream err;
72  
73  // Hidden data members.
74      private JobFrontendRef myJobFrontend;
75      private JobBackendRef myJobBackend;
76  
77      // Mapping from backend file descriptor to backend file output stream.
78      private Map<Integer, BackendFileOutputStream> myOutputStreamForBFD
79              = new HashMap<Integer, BackendFileOutputStream>();
80  
81      // Mapping from frontend file descriptor to backend file output stream.
82      private Map<Integer, BackendFileOutputStream> myOutputStreamForFFD
83              = new HashMap<Integer, BackendFileOutputStream>();
84  
85      // Next backend file descriptor.
86      private int myNextBFD = 1;
87  
88  // Exported constructors.
89      /**
90       * Construct a new backend file writer.
91       *
92       * @param theJobFrontend Job Frontend.
93       * @param theJobBackend Job Backend.
94       */
95      public BackendFileWriter(JobFrontendRef theJobFrontend,
96              JobBackendRef theJobBackend) {
97          myJobFrontend = theJobFrontend;
98          myJobBackend = theJobBackend;
99  
100         // Set up output streams for stdout and stderr.
101         BackendFileOutputStream outstream
102                 = new BackendFileOutputStream(myJobFrontend, myJobBackend, 1);
103         BackendFileOutputStream errstream
104                 = new BackendFileOutputStream(myJobFrontend, myJobBackend, 2);
105         myOutputStreamForFFD.put(1, outstream);
106         myOutputStreamForFFD.put(2, errstream);
107 
108         // Set up print streams for stdout and stderr.
109         out
110                 = new PrintStream(new LineBufferedOutputStream(outstream),
111                         true);
112         err
113                 = new PrintStream(new LineBufferedOutputStream(errstream),
114                         true);
115     }
116 
117 // Exported operations.
118     /**
119      * Open a backend file output stream on the given file.
120      *
121      * @param file File.
122      * @param append True to append, false to overwrite.
123      * @return Backend file output stream.
124      * @exception IOException Thrown if an I/O error occurred.
125      * @throws java.io.IOException if any.
126      */
127     public BackendFileOutputStream open(File file,
128             boolean append)
129             throws IOException {
130         BackendFileOutputStream stream = null;
131         int bfd = 0;
132         int ffd = 0;
133 
134         synchronized (this) {
135             stream = new BackendFileOutputStream(myJobFrontend, myJobBackend);
136             bfd = myNextBFD++;
137             myOutputStreamForBFD.put(bfd, stream);
138         }
139 
140         ffd = stream.open(bfd, file, append);
141 
142         synchronized (this) {
143             myOutputStreamForFFD.put(ffd, stream);
144         }
145         return stream;
146     }
147 
148     /**
149      * Report the result of opening the given output file.
150      *
151      * @param theJobFrontend Job Frontend that is calling this method.
152      * @param bfd Backend file descriptor.
153      * @param ffd Frontend file descriptor if success.
154      * @param exc Null if success, exception if failure.
155      */
156     public void outputFileOpenResult(JobFrontendRef theJobFrontend,
157             int bfd,
158             int ffd,
159             IOException exc) {
160         BackendFileOutputStream stream = null;
161         synchronized (this) {
162             stream = myOutputStreamForBFD.remove(bfd);
163         }
164         if (stream != null) {
165             stream.putResult(ffd, exc);
166         }
167     }
168 
169     /**
170      * Report the result of writing the given output file.
171      *
172      * @param theJobFrontend Job Frontend that is calling this method.
173      * @param ffd Frontend file descriptor.
174      * @param exc Null if success, exception if failure.
175      */
176     public void outputFileWriteResult(JobFrontendRef theJobFrontend,
177             int ffd,
178             IOException exc) {
179         BackendFileOutputStream stream = null;
180         synchronized (this) {
181             stream = myOutputStreamForFFD.get(ffd);
182         }
183         if (stream != null) {
184             stream.putResult(ffd, exc);
185         }
186     }
187 
188     /**
189      * Report the result of flushing the given output file.
190      *
191      * @param theJobFrontend Job Frontend that is calling this method.
192      * @param ffd Frontend file descriptor.
193      * @param exc Null if success, exception if failure.
194      */
195     public void outputFileFlushResult(JobFrontendRef theJobFrontend,
196             int ffd,
197             IOException exc) {
198         BackendFileOutputStream stream = null;
199         synchronized (this) {
200             stream = myOutputStreamForFFD.get(ffd);
201         }
202         if (stream != null) {
203             stream.putResult(ffd, exc);
204         }
205     }
206 
207     /**
208      * Report the result of closing the given output file.
209      *
210      * @param theJobFrontend Job Frontend that is calling this method.
211      * @param ffd Frontend file descriptor.
212      * @param exc Null if success, exception if failure.
213      */
214     public void outputFileCloseResult(JobFrontendRef theJobFrontend,
215             int ffd,
216             IOException exc) {
217         BackendFileOutputStream stream = null;
218         synchronized (this) {
219             stream = myOutputStreamForFFD.remove(ffd);
220         }
221         if (stream != null) {
222             stream.putResult(ffd, exc);
223         }
224     }
225 
226 }