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