1 /*
2  *  (C) 2001 by Argonne National Laboratory
3  *      See COPYRIGHT in top-level directory.
4  */
5 
6 /*
7  *  @author  Anthony Chan
8  */
9 
10 package logformat.slog2.output;
11 
12 import java.io.*;
13 
14 import base.io.MixedRandomAccessFile;
15 import base.io.BufArrayOutputStream;
16 import base.io.MixedDataOutputStream;
17 // import base.io.DataIO;
18 import base.io.MixedDataIO;
19 import base.drawable.TimeBoundingBox;
20 import logformat.slog2.*;
21 
22 public class OutputLog
23 {
24     private MixedRandomAccessFile  rand_file;
25     private BufArrayOutputStream   bary_outs;
26     private MixedDataOutputStream  data_outs;
27 
28     private Header                 filehdr;
29     private TreeDir                treedir;
30 
31     // Last Treenode's FileBlockPtr
32     private FileBlockPtr           node_blockptr;
33 
OutputLog( String filename )34     public OutputLog( String filename )
35     {
36         rand_file = null;
37         try {
38             rand_file = new MixedRandomAccessFile( filename, "rw" );
39         // } catch ( FileNotFoundException ferr ) {
40         } catch ( IOException ferr ) {
41             ferr.printStackTrace();
42             System.exit( 1 );
43         }
44 
45         filehdr        = new Header();
46 
47         /*
48            Const.LEAF_BYTESIZE is the INITIAL size for
49            BufArrayOutputStream's buffer which can still grow as needed
50         */
51         bary_outs      = new BufArrayOutputStream(
52                                  filehdr.getTreeLeafByteSize() );
53         data_outs      = new MixedDataOutputStream( bary_outs );
54 
55         treedir        = new TreeDir();
56         node_blockptr  = null;
57 
58         // Write the initialized Header to Disk
59         this.writeHeader();
60     }
61 
setTreeLeafByteSize( int in_bytesize )62     public void setTreeLeafByteSize( int in_bytesize )
63     {
64         filehdr.setTreeLeafByteSize( in_bytesize );
65         bary_outs      = new BufArrayOutputStream(
66                                  filehdr.getTreeLeafByteSize() );
67         data_outs      = new MixedDataOutputStream( bary_outs );
68     }
69 
getTreeLeafByteSize()70     public int getTreeLeafByteSize()
71     {
72         return filehdr.getTreeLeafByteSize();
73     }
74 
setNumChildrenPerNode( short num_leafs )75     public void setNumChildrenPerNode( short num_leafs )
76     {
77         filehdr.setNumChildrenPerNode( num_leafs );
78     }
79 
getNumChildrenPerNode()80     public short getNumChildrenPerNode()
81     {
82         return filehdr.getNumChildrenPerNode();
83     }
84 
writeTreeNode( TreeNode treenode )85     public void writeTreeNode( TreeNode treenode )
86     {
87         TreeNodeID             treedir_key;
88         TreeDirValue           treedir_val;
89         TimeBoundingBox        timebox;
90 
91         try {
92             // Save the LAST input TreeNode's FileBlockPtr
93             node_blockptr = new FileBlockPtr( rand_file.getFilePointer(),
94                                               treenode.getNodeByteSize() );
95         } catch ( IOException ioerr ) {
96             ioerr.printStackTrace();
97             System.exit( 1 );
98         }
99 
100         // Create key and value pair for the TreeDir
101         treedir_key   = new TreeNodeID( treenode.getTreeNodeID() );
102         timebox = new TimeBoundingBox( treenode );
103         treedir_val   = new TreeDirValue( timebox, node_blockptr );
104         treedir.put( treedir_key, treedir_val );
105 
106         // Reset various file pointers of the TreeNode before writing to file
107         treenode.setFileBlockPtr( node_blockptr.getFilePointer(),
108                                   node_blockptr.getBlockSize() );
109 
110         // treenode's mergeVerticalShadowBufs() and shiftHorizontalShadowBuf()
111         // updates ShadowBufs which are NOT being saved to disk in this call.
112 
113         // Merge ShadowBufs Vertically from childnode's
114         treenode.mergeVerticalShadowBufs();
115         // The TreeNode.shiftHorizontalShadowBuf() has to be called
116         // after TreeNode.setFileBlockPtr( node_blockptr )
117         treenode.shiftHorizontalShadowBuf();
118 
119         // System.err.println( "OutputLog.writeTreeNode("
120         //                   + treenode.getTreeNodeID() + "): START" );
121 
122         // Clear any unwritten data in BufArrayOutputStream's buffer
123         bary_outs.reset();
124         try {
125             // Save TreeNode to BufArrayOutputStream through DataOutputStream
126             treenode.writeObject( data_outs );
127             data_outs.flush();
128             // Copy the content of BufArrayOutputStream to RandomAccessFile
129             rand_file.write( bary_outs.getByteArrayBuf(),
130                              0, bary_outs.size() );
131             if ( bary_outs.size() > filehdr.getMaxBufferByteSize() )
132                 filehdr.setMaxBufferByteSize( bary_outs.size() );
133         } catch ( IOException ioerr ) {
134             ioerr.printStackTrace();
135             System.exit( 1 );
136         }
137 
138         // System.err.println( "OutputLog.writeTreeNode("
139         //                   + treenode.getTreeNodeID() + "): END" );
140 
141         /* debugging */
142         // System.out.println( "\n" + treenode.toString() + "\n" );
143         // System.out.flush();
144     }
145 
writeFilePart( final MixedDataIO filepart, FileBlockPtr blockptr )146     private void writeFilePart( final MixedDataIO   filepart,
147                                       FileBlockPtr  blockptr )
148     {
149         int          blocksize  = 0;
150 
151         try {
152             // Update FilePointer of the Header's FileBlockPtr to "filepart"
153             blockptr.setFilePointer( rand_file.getFilePointer() );
154         } catch ( IOException ioerr ) {
155             ioerr.printStackTrace();
156             System.exit( 1 );
157         }
158 
159         // Clear any unwritten data in BufArrayOutputStream's buffer
160         bary_outs.reset();
161         try {
162             // filepart.writeObject() needs a MixedDataOutput type argument
163             filepart.writeObject( data_outs );
164             data_outs.flush();
165             // Copy the content of BufArrayOutputStream to RandomAccessFile
166             rand_file.write( bary_outs.getByteArrayBuf(),
167                              0, bary_outs.size() );
168             if ( bary_outs.size() > filehdr.getMaxBufferByteSize() )
169                 filehdr.setMaxBufferByteSize( bary_outs.size() );
170             blocksize = (int)( rand_file.getFilePointer()
171                              - blockptr.getFilePointer() );
172         } catch ( IOException ioerr ) {
173             ioerr.printStackTrace();
174             System.exit( 1 );
175         }
176 
177         // Update BlockSize of the Header's FileBlockPtr to "filepart"
178         blockptr.setBlockSize( blocksize );
179 
180         /* debugging */
181         // System.out.println( filepart.toString() );
182         // System.out.flush();
183     }
184 
writeCategoryMap( final CategoryMap objdefs )185     public void writeCategoryMap( final CategoryMap objdefs )
186     {
187         writeFilePart( objdefs, filehdr.blockptr2categories );
188     }
189 
writeLineIDMapList( final LineIDMapList lineIDmaps )190     public void writeLineIDMapList( final LineIDMapList lineIDmaps )
191     {
192         writeFilePart( lineIDmaps, filehdr.blockptr2lineIDmaps );
193     }
194 
writeTreeDir()195     private void writeTreeDir()
196     {
197         writeFilePart( treedir, filehdr.blockptr2treedir );
198     }
199 
writeHeader()200     private void writeHeader()
201     {
202         // Update the Header if necessary
203         if ( node_blockptr != null ) {
204             filehdr.blockptr2treeroot.setFileBlockPtr(
205                 node_blockptr.getFilePointer(), node_blockptr.getBlockSize() );
206             filehdr.setMaxTreeDepth( treedir.getTreeRootID().depth );
207         }
208 
209         // Clear any unwritten data in BufArrayOutputStream's buffer
210         bary_outs.reset();
211         try {
212             filehdr.writeObject( data_outs );
213             data_outs.flush();
214             // Copy the content of BufArrayOutputStream to RandomAccessFile
215             rand_file.seek( 0 );
216             rand_file.write( bary_outs.getByteArrayBuf(),
217                              0, bary_outs.size() );
218         } catch ( IOException ioerr ) {
219             ioerr.printStackTrace();
220             System.exit( 1 );
221         }
222     }
223 
close()224     public void close()
225     {
226         this.writeTreeDir();
227         // System.out.println( treedir.toString() );
228         this.writeHeader();
229         System.out.println( filehdr.toString() );
230 
231         try {
232             // ? data_outs.close() calls bary_outs.close();
233             data_outs.close();
234             rand_file.close();
235         } catch ( IOException ioerr ) {
236             ioerr.printStackTrace();
237             System.exit( 1 );
238         }
239     }
240 
finalize()241     protected void finalize() throws Throwable
242     {
243         try {
244             close();
245         } finally {
246             super.finalize();
247         }
248     }
249 }
250