MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_compress.c
1 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /* Written by Sinisa Milivojevic <sinisa@mysql.com> */
17 
18 #include <my_global.h>
19 #ifdef HAVE_COMPRESS
20 #include <my_sys.h>
21 #ifndef SCO
22 #include <m_string.h>
23 #endif
24 #include <zlib.h>
25 
26 /*
27  This replaces the packet with a compressed packet
28 
29  SYNOPSIS
30  my_compress()
31  packet Data to compress. This is is replaced with the compressed data.
32  len Length of data to compress at 'packet'
33  complen out: 0 if packet was not compressed
34 
35  RETURN
36  1 error. 'len' is not changed'
37  0 ok. In this case 'len' contains the size of the compressed packet
38 */
39 
40 my_bool my_compress(uchar *packet, size_t *len, size_t *complen)
41 {
42  DBUG_ENTER("my_compress");
43  if (*len < MIN_COMPRESS_LENGTH)
44  {
45  *complen=0;
46  DBUG_PRINT("note",("Packet too short: Not compressed"));
47  }
48  else
49  {
50  uchar *compbuf=my_compress_alloc(packet,len,complen);
51  if (!compbuf)
52  DBUG_RETURN(*complen ? 0 : 1);
53  memcpy(packet,compbuf,*len);
54  my_free(compbuf);
55  }
56  DBUG_RETURN(0);
57 }
58 
59 
60 uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen)
61 {
62  uchar *compbuf;
63  uLongf tmp_complen;
64  int res;
65  *complen= *len * 120 / 100 + 12;
66 
67  if (!(compbuf= (uchar *) my_malloc(*complen, MYF(MY_WME))))
68  return 0; /* Not enough memory */
69 
70  tmp_complen= (uint) *complen;
71  res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len);
72  *complen= tmp_complen;
73 
74  if (res != Z_OK)
75  {
76  my_free(compbuf);
77  return 0;
78  }
79 
80  if (*complen >= *len)
81  {
82  *complen= 0;
83  my_free(compbuf);
84  DBUG_PRINT("note",("Packet got longer on compression; Not compressed"));
85  return 0;
86  }
87  /* Store length of compressed packet in *len */
88  swap_variables(size_t, *len, *complen);
89  return compbuf;
90 }
91 
92 
93 /*
94  Uncompress packet
95 
96  SYNOPSIS
97  my_uncompress()
98  packet Compressed data. This is is replaced with the orignal data.
99  len Length of compressed data
100  complen Length of the packet buffer (must be enough for the original
101  data)
102 
103  RETURN
104  1 error
105  0 ok. In this case 'complen' contains the updated size of the
106  real data.
107 */
108 
109 my_bool my_uncompress(uchar *packet, size_t len, size_t *complen)
110 {
111  uLongf tmp_complen;
112  DBUG_ENTER("my_uncompress");
113 
114  if (*complen) /* If compressed */
115  {
116  uchar *compbuf= (uchar *) my_malloc(*complen,MYF(MY_WME));
117  int error;
118  if (!compbuf)
119  DBUG_RETURN(1); /* Not enough memory */
120 
121  tmp_complen= (uint) *complen;
122  error= uncompress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet,
123  (uLong) len);
124  *complen= tmp_complen;
125  if (error != Z_OK)
126  { /* Probably wrong packet */
127  DBUG_PRINT("error",("Can't uncompress packet, error: %d",error));
128  my_free(compbuf);
129  DBUG_RETURN(1);
130  }
131  memcpy(packet, compbuf, *complen);
132  my_free(compbuf);
133  }
134  else
135  *complen= len;
136  DBUG_RETURN(0);
137 }
138 
139 /*
140  Internal representation of the frm blob is:
141 
142  ver 4 bytes
143  orglen 4 bytes
144  complen 4 bytes
145 */
146 
147 #define BLOB_HEADER 12
148 
149 
150 /*
151  packfrm is a method used to compress the frm file for storage in a
152  handler. This method was developed for the NDB handler and has been moved
153  here to serve also other uses.
154 
155  SYNOPSIS
156  packfrm()
157  data Data reference to frm file data.
158  len Length of frm file data
159  out:pack_data Reference to the pointer to the packed frm data
160  out:pack_len Length of packed frm file data
161 
162  NOTES
163  data is replaced with compressed content
164 
165  RETURN VALUES
166  0 Success
167  >0 Failure
168 */
169 
170 int packfrm(uchar *data, size_t len,
171  uchar **pack_data, size_t *pack_len)
172 {
173  int error;
174  size_t org_len, comp_len, blob_len;
175  uchar *blob;
176  DBUG_ENTER("packfrm");
177  DBUG_PRINT("enter", ("data: 0x%lx len: %lu", (long) data, (ulong) len));
178 
179  error= 1;
180  org_len= len;
181  if (my_compress((uchar*)data, &org_len, &comp_len))
182  goto err;
183 
184  DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", (ulong) org_len,
185  (ulong) comp_len));
186  DBUG_DUMP("compressed", data, org_len);
187 
188  error= 2;
189  blob_len= BLOB_HEADER + org_len;
190  if (!(blob= (uchar*) my_malloc(blob_len,MYF(MY_WME))))
191  goto err;
192 
193  /* Store compressed blob in machine independent format */
194  int4store(blob, 1);
195  int4store(blob+4, (uint32) len);
196  int4store(blob+8, (uint32) org_len); /* compressed length */
197 
198  /* Copy frm data into blob, already in machine independent format */
199  memcpy(blob+BLOB_HEADER, data, org_len);
200 
201  *pack_data= blob;
202  *pack_len= blob_len;
203  error= 0;
204 
205  DBUG_PRINT("exit", ("pack_data: 0x%lx pack_len: %lu",
206  (long) *pack_data, (ulong) *pack_len));
207 err:
208  DBUG_RETURN(error);
209 
210 }
211 
212 /*
213  unpackfrm is a method used to decompress the frm file received from a
214  handler. This method was developed for the NDB handler and has been moved
215  here to serve also other uses for other clustered storage engines.
216 
217  SYNOPSIS
218  unpackfrm()
219  pack_data Data reference to packed frm file data
220  out:unpack_data Reference to the pointer to the unpacked frm data
221  out:unpack_len Length of unpacked frm file data
222 
223  RETURN VALUES¨
224  0 Success
225  >0 Failure
226 */
227 
228 int unpackfrm(uchar **unpack_data, size_t *unpack_len,
229  const uchar *pack_data)
230 {
231  uchar *data;
232  size_t complen, orglen;
233  ulong ver;
234  DBUG_ENTER("unpackfrm");
235  DBUG_PRINT("enter", ("pack_data: 0x%lx", (long) pack_data));
236 
237  ver= uint4korr(pack_data);
238  orglen= uint4korr(pack_data+4);
239  complen= uint4korr(pack_data+8);
240 
241  DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu",
242  ver, (ulong) complen, (ulong) orglen));
243  DBUG_DUMP("blob->data", pack_data + BLOB_HEADER, complen);
244 
245  if (ver != 1)
246  DBUG_RETURN(1);
247  if (!(data= my_malloc(MY_MAX(orglen, complen), MYF(MY_WME))))
248  DBUG_RETURN(2);
249  memcpy(data, pack_data + BLOB_HEADER, complen);
250 
251  if (my_uncompress(data, complen, &orglen))
252  {
253  my_free(data);
254  DBUG_RETURN(3);
255  }
256 
257  *unpack_data= data;
258  *unpack_len= orglen;
259 
260  DBUG_PRINT("exit", ("frmdata: 0x%lx len: %lu", (long) *unpack_data,
261  (ulong) *unpack_len));
262  DBUG_RETURN(0);
263 }
264 #endif /* HAVE_COMPRESS */