View Javadoc

1   /***
2    *
3    * Copyright 2004 Hiram Chirino
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  package org.codehaus.activemq.journal.impl;
19  
20  import java.io.DataInput;
21  import java.io.DataOutput;
22  import java.io.IOException;
23  import java.nio.ByteBuffer;
24  import java.util.zip.CRC32;
25  
26  /***
27   * Serializes/Deserializes record header information. 
28   * 
29   * @version $Revision: 1.1 $
30   */
31  public class RecordFooter {
32  	
33  	static final public int SELECTED_CHECKSUM_ALGORITHIM;
34  	static final public int NO_CHECKSUM_ALGORITHIM=0;
35  	static final public int HASH_CHECKSUM_ALGORITHIM=1;
36  	static final public int CRC32_CHECKSUM_ALGORITHIM=2;
37  	
38  	static {
39  		String type = System.getProperty("org.codehaus.activemq.journal.impl.SELECTED_CHECKSUM_ALGORITHIM", "hash");
40  		if( "none".equals(type) ) {
41  			SELECTED_CHECKSUM_ALGORITHIM = NO_CHECKSUM_ALGORITHIM;			
42  		} else if( "crc32".equals(type) ) {
43  			SELECTED_CHECKSUM_ALGORITHIM = CRC32_CHECKSUM_ALGORITHIM;			
44  		} else if( "hash".equals(type) ) {
45  			SELECTED_CHECKSUM_ALGORITHIM = HASH_CHECKSUM_ALGORITHIM;			
46  		} else {
47  			System.err.println("System property 'org.codehaus.activemq.journal.impl.SELECTED_CHECKSUM_ALGORITHIM' not set properly.  Valid values are: 'none', 'hash', or 'crc32'");
48  			SELECTED_CHECKSUM_ALGORITHIM = NO_CHECKSUM_ALGORITHIM;			
49  		}
50  	}
51  	
52      static final public int RECORD_FOOTER_SIZE=19;
53      static final public byte[] END_OF_RECORD 	= new byte[] { 'E', 'o', 'R' }; 
54  
55      public long checksum;
56      public long sequenceId;
57  
58  	/***
59  	 * @return
60  	 */
61  	public ByteBuffer toByteBuffer() {
62  		ByteBuffer buff = ByteBuffer.allocate(RECORD_FOOTER_SIZE);
63  		buff.putLong(checksum)
64  		 	.putLong(sequenceId)
65  			.put(END_OF_RECORD)
66  			.flip();
67  		return buff;
68  	}
69  
70  	void writeRecordFooter( DataOutput out ) throws IOException {
71  	    out.writeLong(checksum);
72  	    out.writeLong(sequenceId);
73  	    out.write(END_OF_RECORD);
74  	}
75  	
76  	void readRecordFooter( DataInput in ) throws IOException {
77          checksum = in.readLong();
78          sequenceId = in.readLong();
79          for (int i = 0; i < END_OF_RECORD.length; i++) {
80              byte checkByte = END_OF_RECORD[i];
81              if( in.readByte()!= checkByte ) {
82                  throw new IOException("Not a valid record header.");
83              }
84          }
85  	}
86  
87  	/***
88  	 * 
89  	 */
90  	public void invalidate() {
91  		checksum=-1;
92  		sequenceId=-1;			
93  	}
94  	
95  	public boolean matches(RecordHeader header) {
96  		return header.sequenceId==sequenceId;
97  	}
98  
99  	static public boolean isChecksumingEnabled() {
100 		return SELECTED_CHECKSUM_ALGORITHIM!=NO_CHECKSUM_ALGORITHIM;
101 	}
102 	
103 	public boolean matches(byte data[]) {
104 		return buildChecksum(data)==checksum;
105 	}
106 
107 	static public long buildChecksum(byte[] data) {		
108 		if( SELECTED_CHECKSUM_ALGORITHIM==HASH_CHECKSUM_ALGORITHIM ) {
109 			byte rc[] = new byte[8];
110 			for (int i = 0; i < data.length; i++) {
111 				rc[i%8] ^= data[i];			
112 			}
113 			return (rc[0])|(rc[1]<<1)|(rc[2]<<2)|(rc[3]<<3)|(rc[4]<<4)|(rc[5]<<5)|(rc[6]<<6)|(rc[7]<<7) ;
114 		} else if( SELECTED_CHECKSUM_ALGORITHIM==CRC32_CHECKSUM_ALGORITHIM ) {
115 			CRC32 crc32 = new CRC32();
116 			crc32.update(data);
117 			return crc32.getValue();
118 		} else {
119 			return 0L;
120 		}
121 	}
122 
123 	/***
124 	 * @param header
125 	 * @param data
126 	 */
127 	public void bulkSet(RecordHeader header, byte[] data) {
128 		this.sequenceId = header.sequenceId;
129 		this.checksum = buildChecksum(data);
130 	}
131 
132 }