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 }