Clover coverage report - ActiveIO - 1.0 Coverage timestamp: Fri Apr 22 2005 14:27:22 PDT FRAMES NO FRAMES |
file stats: | LOC: | 310 |  | Methods: | 22
| NCLOC: | 208 |  | Classes: | 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
Source file | Conditionals | Statements | Methods | TOTAL
Record.java | 22.7% | 43.4% | 59.1% | 40.2% |

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.activeio.journal.active;
19 |  |
20 |  |
     import java.io.DataInput;
21 |  |
     import java.io.DataInputStream;
22 |  |
     import java.io.DataOutput;
23 |  |
     import java.io.DataOutputStream;
24 |  |
     import java.io.IOException;
25 |  |
     import java.util.zip.CRC32;
26 |  |
27 |  |
     import org.activeio.Disposable;
28 |  |
     import org.activeio.Packet;
29 |  |
     import org.activeio.adapter.PacketInputStream;
30 |  |
     import org.activeio.adapter.PacketOutputStream;
31 |  |
     import org.activeio.packet.ByteArrayPacket;
32 |  |
33 |  |
34 |  |
     /**
35 |  |
      * Serializes/Deserializes data records.
36 |  |
      *
37 |  |
      * @version $Revision: 1.1 $
38 |  |
      */
39 |  |
     final public class Record implements Disposable {
40 |  |
41 |  |
         static final public int RECORD_HEADER_SIZE=8+Location.SERIALIZED_SIZE;
42 |  |
         static final public int RECORD_FOOTER_SIZE=12+Location.SERIALIZED_SIZE;
43 |  |
         static final public int RECORD_BASE_SIZE=RECORD_HEADER_SIZE+RECORD_FOOTER_SIZE;
44 |  |
45 |  |
         static final public byte[] START_OF_RECORD     = new byte[] { 'S', 'o', 'R' };
46 |  |
         static final public byte[] END_OF_RECORD     = new byte[] { 'E', 'o', 'R', '.' };
47 |  |
48 |  |
         static final public int SELECTED_CHECKSUM_ALGORITHIM;
49 |  |
         static final public int NO_CHECKSUM_ALGORITHIM=0;
50 |  |
         static final public int HASH_CHECKSUM_ALGORITHIM=1;
51 |  |
         static final public int CRC32_CHECKSUM_ALGORITHIM=2;
52 |  |
53 |  |
         static {
54 | 4 |
             String type = System.getProperty("org.activeio.journal.active.SELECTED_CHECKSUM_ALGORITHIM", "none");
55 | 4 |
             if( "none".equals(type) ) {
56 | 4 |
                 SELECTED_CHECKSUM_ALGORITHIM = NO_CHECKSUM_ALGORITHIM;
57 | 0 |
             } else if( "crc32".equals(type) ) {
58 | 0 |
                 SELECTED_CHECKSUM_ALGORITHIM = CRC32_CHECKSUM_ALGORITHIM;
59 | 0 |
             } else if( "hash".equals(type) ) {
60 | 0 |
                 SELECTED_CHECKSUM_ALGORITHIM = HASH_CHECKSUM_ALGORITHIM;
61 |  |
             } else {
62 | 0 |
                 System.err.println("System property 'org.activeio.journal.active.SELECTED_CHECKSUM_ALGORITHIM' not set properly.  Valid values are: 'none', 'hash', or 'crc32'");
63 | 0 |
                 SELECTED_CHECKSUM_ALGORITHIM = NO_CHECKSUM_ALGORITHIM;
64 |  |
             }
65 |  |
         }
66 |  |
67 | 22 |
         static public boolean isChecksumingEnabled() {
68 | 22 |
             return SELECTED_CHECKSUM_ALGORITHIM!=NO_CHECKSUM_ALGORITHIM;
69 |  |
         }
70 |  |
71 |  |
         private final ByteArrayPacket headerFooterPacket = new ByteArrayPacket(new byte[RECORD_BASE_SIZE]);
72 |  |
         private final DataOutputStream headerFooterData = new DataOutputStream(new PacketOutputStream(headerFooterPacket));
73 |  |
74 |  |
         private int payloadLength;
75 |  |
         private Location location;
76 |  |
         private byte recordType;
77 |  |
         private long checksum;
78 |  |
         private Location mark;
79 |  |
         private Packet payload;
80 |  |
81 | 40 |
         public Record() {
82 |  |
         }
83 |  |
84 | 22 |
         public Record(byte recordType, Packet payload, Location mark) throws IOException {
85 | 22 |
             this(null, recordType, payload, mark);
86 |  |
         }
87 |  |
88 | 22 |
         public Record(Location location, byte recordType, Packet payload, Location mark) throws IOException {
89 | 22 |
             this.location = location;
90 | 22 |
             this.recordType = recordType;
91 | 22 |
             this.mark = mark;
92 | 22 |
             this.payload = payload.slice();
93 | 22 |
             this.payloadLength = payload.remaining();
94 | 22 |
             if( isChecksumingEnabled() ) {
95 | 0 |
                 checksum(new DataInputStream(new PacketInputStream(this.payload)));
96 |  |
             }
97 |  |
98 | 22 |
             writeHeader(headerFooterData);
99 | 22 |
             writeFooter(headerFooterData);
100 |  |
         }
101 |  |
102 | 22 |
         public void setLocation(Location location) throws IOException {
103 | 22 |
             this.location = location;
104 | 22 |
             headerFooterPacket.clear();
105 | 22 |
             headerFooterPacket.position(8);
106 | 22 |
             location.writeToDataOutput(headerFooterData);
107 | 22 |
             headerFooterPacket.position(RECORD_HEADER_SIZE+8);
108 | 22 |
             location.writeToDataOutput(headerFooterData);
109 | 22 |
             payload.clear();
110 | 22 |
             headerFooterPacket.position(0);
111 | 22 |
             headerFooterPacket.limit(RECORD_HEADER_SIZE);
112 |  |
         }
113 |  |
114 | 22 |
         private void writeHeader( DataOutput out ) throws IOException {
115 | 22 |
             out.write(START_OF_RECORD);
116 | 22 |
             out.writeByte(recordType);
117 | 22 |
             out.writeInt(payloadLength);
118 | 22 |
             if( location!=null )
119 | 0 |
                 location.writeToDataOutput(out);
120 |  |
             else
121 | 22 |
                 out.writeLong(0);
122 |  |
         }
123 |  |
124 | 40 |
         public void readHeader( DataInput in ) throws IOException {
125 | 40 |
             readAndCheckConstant(in, START_OF_RECORD, "Invalid record header: start of record constant missing.");
126 | 30 |
             recordType = in.readByte();
127 | 30 |
             payloadLength = in.readInt();
128 | 30 |
             if( payloadLength < 0 )
129 | 0 |
                 throw new IOException("Invalid record header: record length cannot be less than zero.");
130 | 30 |
             location = Location.readFromDataInput(in);
131 |  |
         }
132 |  |
133 | 22 |
         private void writeFooter( DataOutput out ) throws IOException {
134 | 22 |
             out.writeLong(checksum);
135 | 22 |
             if( location!=null )
136 | 0 |
                 location.writeToDataOutput(out);
137 |  |
             else
138 | 22 |
                 out.writeLong(0);
139 | 22 |
             out.write(END_OF_RECORD);
140 |  |
         }
141 |  |
142 | 0 |
         public void readFooter( DataInput in ) throws IOException {
143 | 0 |
             long l = in.readLong();
144 | 0 |
             if( isChecksumingEnabled() ) {
145 | 0 |
                 if( l!=checksum )
146 | 0 |
                     throw new IOException("Invalid record footer: checksum does not match.");
147 |  |
             } else {
148 | 0 |
                 checksum = l;
149 |  |
             }
150 |  |
151 | 0 |
             Location loc = Location.readFromDataInput(in);
152 | 0 |
             if( !loc.equals(location) )
153 | 0 |
                 throw new IOException("Invalid record footer: location id does not match.");
154 |  |
155 | 0 |
             readAndCheckConstant(in, END_OF_RECORD, "Invalid record header: end of record constant missing.");
156 |  |
         }
157 |  |
158 |  |
         /**
159 |  |
          * @param randomAccessFile
160 |  |
          * @throws IOException
161 |  |
          */
162 | 0 |
         public void checksum(DataInput in) throws IOException {
163 | 0 |
             if( SELECTED_CHECKSUM_ALGORITHIM==HASH_CHECKSUM_ALGORITHIM ) {
164 |  |
165 | 0 |
                 byte  buffer[] = new byte[1024];
166 | 0 |
                 byte rc[] = new byte[8];
167 | 0 |
                 for (int i = 0; i < payloadLength;) {
168 | 0 |
                     int l = Math.min(buffer.length, payloadLength-i);
169 | 0 |
                     in.readFully(buffer,0,l);
170 | 0 |
                     for (int j = 0; j < l; j++) {
171 | 0 |
                         rc[j%8] ^= buffer[j];
172 |  |
                     }
173 | 0 |
                     i+=l;
174 |  |
                 }
175 | 0 |
                 checksum = (rc[0])|(rc[1]<<1)|(rc[2]<<2)|(rc[3]<<3)|(rc[4]<<4)|(rc[5]<<5)|(rc[6]<<6)|(rc[7]<<7) ;
176 |  |
177 | 0 |
             } else if( SELECTED_CHECKSUM_ALGORITHIM==CRC32_CHECKSUM_ALGORITHIM ) {
178 | 0 |
                 byte  buffer[] = new byte[1024];
179 | 0 |
                 CRC32 crc32 = new CRC32();
180 | 0 |
                 for (int i = 0; i < payloadLength;) {
181 | 0 |
                     int l = Math.min(buffer.length, payloadLength-i);
182 | 0 |
                     in.readFully(buffer,0,l);
183 | 0 |
                     crc32.update(buffer,0,l);
184 | 0 |
                     i+=l;
185 |  |
                 }
186 | 0 |
                 checksum = crc32.getValue();
187 |  |
             } else {
188 | 0 |
                 checksum = 0L;
189 |  |
             }
190 |  |
         }
191 |  |
192 |  |
193 |  |
         /**
194 |  |
          */
195 | 40 |
         private void readAndCheckConstant(DataInput in, byte[] byteConstant, String errorMessage ) throws IOException {
196 | 40 |
             for (int i = 0; i < byteConstant.length; i++) {
197 | 100 |
                 byte checkByte = byteConstant[i];
198 | 100 |
                 if( in.readByte()!= checkByte ) {
199 | 10 |
                     throw new IOException(errorMessage);
200 |  |
                 }
201 |  |
             }
202 |  |
         }
203 |  |
204 | 0 |
         public boolean readFromPacket(Packet packet) throws IOException {
205 | 0 |
             Packet dup = packet.duplicate();
206 |  |
207 | 0 |
             if( dup.remaining() < RECORD_HEADER_SIZE )
208 | 0 |
                 return false;
209 | 0 |
             DataInputStream is = new DataInputStream(new PacketInputStream(dup));
210 | 0 |
             readHeader( is );
211 | 0 |
             if( dup.remaining() < payloadLength+RECORD_FOOTER_SIZE ) {
212 | 0 |
                 return false;
213 |  |
             }
214 |  |
215 |  |
             // Set limit to create a slice of the payload.
216 | 0 |
             dup.limit(dup.position()+payloadLength);
217 | 0 |
             this.payload = dup.slice();
218 | 0 |
             if( isChecksumingEnabled() ) {
219 | 0 |
                 checksum(new DataInputStream(new PacketInputStream(payload)));
220 |  |
             }
221 |  |
222 |  |
             // restore the limit and seek to the footer.
223 | 0 |
             dup.limit(packet.limit());
224 | 0 |
             dup.position(dup.position()+payloadLength);
225 | 0 |
             readFooter(is);
226 |  |
227 |  |
             // If every thing went well.. advance the position of the orignal packet.
228 | 0 |
             packet.position(dup.position());
229 | 0 |
             dup.dispose();
230 | 0 |
             return true;
231 |  |
         }
232 |  |
233 |  |
         /**
234 |  |
          * @return Returns the checksum.
235 |  |
          */
236 | 0 |
         public long getChecksum() {
237 | 0 |
             return checksum;
238 |  |
         }
239 |  |
240 |  |
         /**
241 |  |
          * @return Returns the length.
242 |  |
          */
243 | 22 |
         public int getPayloadLength() {
244 | 22 |
             return payloadLength;
245 |  |
         }
246 |  |
247 |  |
         /**
248 |  |
          * @return Returns the length of the record .
249 |  |
          */
250 | 0 |
         public int getRecordLength() {
251 | 0 |
             return payloadLength+Record.RECORD_BASE_SIZE;
252 |  |
         }
253 |  |
254 |  |
         /**
255 |  |
          * @return Returns the location.
256 |  |
          */
257 | 0 |
         public Location getLocation() {
258 | 0 |
             return location;
259 |  |
         }
260 |  |
261 |  |
         /**
262 |  |
          * @return Returns the mark.
263 |  |
          */
264 | 0 |
         public Location getMark() {
265 | 0 |
             return mark;
266 |  |
         }
267 |  |
268 |  |
         /**
269 |  |
          * @return Returns the payload.
270 |  |
          */
271 | 0 |
         public Packet getPayload() {
272 | 0 |
             return payload;
273 |  |
         }
274 |  |
275 |  |
         /**
276 |  |
          * @return Returns the recordType.
277 |  |
          */
278 | 8 |
         public byte getRecordType() {
279 | 8 |
             return recordType;
280 |  |
         }
281 |  |
282 | 36 |
         public boolean hasRemaining() {
283 | 36 |
             return headerFooterPacket.position()!=RECORD_BASE_SIZE;
284 |  |
         }
285 |  |
286 | 22 |
         public void read(Packet packet) {
287 |  |
288 |  |
             // push the header
289 | 22 |
             headerFooterPacket.read(packet);
290 |  |
             // push the payload.
291 | 22 |
             payload.read(packet);
292 |  |
293 |  |
             // Can we switch to the footer now?
294 | 22 |
             if( !payload.hasRemaining() && headerFooterPacket.position()==RECORD_HEADER_SIZE ) {
295 | 22 |
                 headerFooterPacket.position(RECORD_HEADER_SIZE);
296 | 22 |
                  headerFooterPacket.limit(RECORD_BASE_SIZE);
297 | 22 |
                 headerFooterPacket.read(packet);
298 |  |
             }
299 |  |
300 |  |
         }
301 |  |
302 | 0 |
         public void dispose() {
303 | 0 |
             if( payload!=null ) {
304 | 0 |
                 payload.dispose();
305 | 0 |
                 payload=null;
306 |  |
             }
307 |  |
         }
308 |  |
309 |  |
     }
310 |  |