KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > protocols > COMPRESS


1 package org.jgroups.protocols;
2
3 import org.jgroups.Event;
4 import org.jgroups.Header;
5 import org.jgroups.Message;
6 import org.jgroups.Global;
7 import org.jgroups.stack.Protocol;
8 import org.jgroups.util.Util;
9 import org.jgroups.util.Streamable;
10
11 import java.io.*;
12 import java.util.Properties JavaDoc;
13 import java.util.zip.DataFormatException JavaDoc;
14 import java.util.zip.Deflater JavaDoc;
15 import java.util.zip.Inflater JavaDoc;
16
17 /**
18  * Compresses the payload of a message. Goal is to reduce the number of messages sent across the wire.
19  * Should ideally be layered somewhere above a fragmentation protocol (e.g. FRAG).
20  * @author Bela Ban
21  * @version $Id: COMPRESS.java,v 1.7 2005/04/15 13:17:01 belaban Exp $
22  */

23 public class COMPRESS extends Protocol {
24
25     Deflater JavaDoc deflater=null;
26
27     Inflater JavaDoc inflater=null;
28
29
30     /** Values are from 0-9 (0=no compression, 9=best compression) */
31     int compression_level=Deflater.BEST_COMPRESSION; // this is 9
32

33     /** Minimal payload size of a message (in bytes) for compression to kick in */
34     long min_size=500;
35
36     final static String JavaDoc name="COMPRESS";
37
38     public String JavaDoc getName() {
39         return name;
40     }
41
42     public void init() throws Exception JavaDoc {
43         deflater=new Deflater JavaDoc(compression_level);
44         inflater=new Inflater JavaDoc();
45     }
46
47     public void destroy() {
48         deflater.end();
49         deflater=null;
50         inflater.end();
51         inflater=null;
52     }
53
54     public boolean setProperties(Properties JavaDoc props) {
55         String JavaDoc str;
56
57         super.setProperties(props);
58         str=props.getProperty("compression_level");
59         if(str != null) {
60             compression_level=Integer.parseInt(str);
61             props.remove("compression_level");
62         }
63
64         str=props.getProperty("min_size");
65         if(str != null) {
66             min_size=Long.parseLong(str);
67             props.remove("min_size");
68         }
69
70         if(props.size() > 0) {
71             System.err.println("COMPRESS.setProperties(): the following properties are not recognized:");
72             props.list(System.out);
73             return false;
74         }
75         return true;
76     }
77
78
79     /**
80      * If there is no header, we pass the message up. Otherwise we uncompress the payload to its original size.
81      * @param evt
82      */

83     public void up(Event evt) {
84         if(evt.getType() == Event.MSG) {
85             Message msg=(Message)evt.getArg();
86             CompressHeader hdr=(CompressHeader)msg.removeHeader(name);
87             if(hdr != null) {
88                 byte[] compressed_payload=msg.getRawBuffer();
89                 if(compressed_payload != null && compressed_payload.length > 0) {
90                     int original_size=hdr.original_size;
91                     byte[] uncompressed_payload=new byte[original_size];
92                     inflater.reset();
93                     inflater.setInput(compressed_payload, msg.getOffset(), msg.getLength());
94                     try {
95                         inflater.inflate(uncompressed_payload);
96                         if(log.isTraceEnabled())
97                             log.trace("uncompressed " + compressed_payload.length + " bytes to " +
98                                     original_size + " bytes");
99                         msg.setBuffer(uncompressed_payload);
100                     }
101                     catch(DataFormatException JavaDoc e) {
102                         if(log.isErrorEnabled()) log.error("exception on uncompression: " + Util.printStackTrace(e));
103                     }
104                 }
105             }
106         }
107         passUp(evt);
108     }
109
110
111
112     /**
113      * We compress the payload if it is larger than <code>min_size</code>. In this case we add a header containing
114      * the original size before compression. Otherwise we add no header.<br/>
115      * Note that we compress either the entire buffer (if offset/length are not used), or a subset (if offset/length
116      * are used)
117      * @param evt
118      */

119     public void down(Event evt) {
120         if(evt.getType() == Event.MSG) {
121             Message msg=(Message)evt.getArg();
122             int length=msg.getLength(); // takes offset/length (if set) into account
123
if(length >= min_size) {
124                 byte[] payload=msg.getRawBuffer(); // here we get the ref so we can avoid copying
125
byte[] compressed_payload=new byte[length];
126                 deflater.reset();
127                 deflater.setInput(payload, msg.getOffset(), length);
128                 deflater.finish();
129                 deflater.deflate(compressed_payload);
130                 int compressed_size=deflater.getTotalOut();
131                 byte[] new_payload=new byte[compressed_size];
132                 System.arraycopy(compressed_payload, 0, new_payload, 0, compressed_size);
133                 msg.setBuffer(new_payload);
134                 msg.putHeader(name, new CompressHeader(length));
135                 if(log.isTraceEnabled())
136                     log.trace("compressed payload from " + length + " bytes to " + compressed_size + " bytes");
137             }
138         }
139         passDown(evt);
140     }
141
142
143
144
145     public static class CompressHeader extends Header implements Streamable {
146         int original_size=0;
147
148         public CompressHeader() {
149             super();
150         }
151
152         public CompressHeader(int s) {
153             original_size=s;
154         }
155
156
157         public long size() {
158             return Global.INT_SIZE;
159         }
160
161         public void writeExternal(ObjectOutput out) throws IOException {
162             out.writeInt(original_size);
163         }
164
165         public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException JavaDoc {
166             original_size=in.readInt();
167         }
168
169         public void writeTo(DataOutputStream out) throws IOException {
170             out.writeInt(original_size);
171         }
172
173         public void readFrom(DataInputStream in) throws IOException, IllegalAccessException JavaDoc, InstantiationException JavaDoc {
174             original_size=in.readInt();
175         }
176     }
177 }
178
Popular Tags