@@ -98,24 +98,25 @@ func newCompIO(mc *mysqlConn) *compIO {
98
98
99
99
func (c * compIO ) readNext (need int ) ([]byte , error ) {
100
100
for c .buff .Len () < need {
101
- if err := c .uncompressPacket (); err != nil {
101
+ if err := c .readCompressedPacket (); err != nil {
102
102
return nil , err
103
103
}
104
104
}
105
105
data := c .buff .Next (need )
106
106
return data [:need :need ], nil // prevent caller writes into c.buff
107
107
}
108
108
109
- func (c * compIO ) uncompressPacket () error {
109
+ func (c * compIO ) readCompressedPacket () error {
110
110
header , err := c .mc .buf .readNext (7 ) // size of compressed header
111
111
if err != nil {
112
112
return err
113
113
}
114
+ _ = header [6 ] // bounds check hint to compiler; guaranteed by readNext
114
115
115
116
// compressed header structure
116
- comprLength := int (uint32 (header [0 ]) | uint32 (header [1 ])<< 8 | uint32 (header [2 ])<< 16 )
117
- uncompressedLength := int (uint32 (header [4 ]) | uint32 (header [5 ])<< 8 | uint32 (header [6 ])<< 16 )
117
+ comprLength := getUint24 (header [0 :3 ])
118
118
compressionSequence := uint8 (header [3 ])
119
+ uncompressedLength := getUint24 (header [4 :7 ])
119
120
if debugTrace {
120
121
fmt .Printf ("uncompress cmplen=%v uncomplen=%v pkt_cmp_seq=%v expected_cmp_seq=%v\n " ,
121
122
comprLength , uncompressedLength , compressionSequence , c .mc .sequence )
@@ -171,43 +172,42 @@ func (c *compIO) writePackets(packets []byte) (int, error) {
171
172
buf := & c .buff
172
173
173
174
for dataLen > 0 {
174
- buf .Reset ()
175
- payloadLen := dataLen
176
- if payloadLen > maxPayloadLen {
177
- payloadLen = maxPayloadLen
178
- }
175
+ payloadLen := min (maxPayloadLen , dataLen )
179
176
payload := packets [:payloadLen ]
180
177
uncompressedLen := payloadLen
181
178
182
- if _ , err := buf .Write (blankHeader ); err != nil {
183
- return 0 , err
184
- }
179
+ buf .Reset ()
180
+ buf .Write (blankHeader ) // Buffer.Write() never returns error
185
181
186
182
// If payload is less than minCompressLength, don't compress.
187
183
if uncompressedLen < minCompressLength {
188
- if _ , err := buf .Write (payload ); err != nil {
189
- return 0 , err
190
- }
184
+ buf .Write (payload )
191
185
uncompressedLen = 0
192
186
} else {
193
187
zCompress (payload , buf )
188
+ // do not compress if compressed data is larger than uncompressed data
189
+ // I intentionally miss 7 byte header in the buf; compress should compress more than 7 bytes.
190
+ if buf .Len () > uncompressedLen {
191
+ buf .Reset ()
192
+ buf .Write (blankHeader )
193
+ buf .Write (payload )
194
+ uncompressedLen = 0
195
+ }
194
196
}
195
197
196
- if err := c .writeCompressedPacket (buf .Bytes (), uncompressedLen ); err != nil {
198
+ if err := c .mc . writeCompressedPacket (buf .Bytes (), uncompressedLen ); err != nil {
197
199
return 0 , err
198
200
}
199
201
dataLen -= payloadLen
200
202
packets = packets [payloadLen :]
201
- buf .Reset ()
202
203
}
203
204
204
205
return totalBytes , nil
205
206
}
206
207
207
208
// writeCompressedPacket writes a compressed packet with header.
208
209
// data should start with 7 size space for header followed by payload.
209
- func (c * compIO ) writeCompressedPacket (data []byte , uncompressedLen int ) error {
210
- mc := c .mc
210
+ func (mc * mysqlConn ) writeCompressedPacket (data []byte , uncompressedLen int ) error {
211
211
comprLength := len (data ) - 7
212
212
if debugTrace {
213
213
fmt .Printf (
@@ -216,16 +216,9 @@ func (c *compIO) writeCompressedPacket(data []byte, uncompressedLen int) error {
216
216
}
217
217
218
218
// compression header
219
- data [0 ] = byte (0xff & comprLength )
220
- data [1 ] = byte (0xff & (comprLength >> 8 ))
221
- data [2 ] = byte (0xff & (comprLength >> 16 ))
222
-
219
+ putUint24 (data [0 :3 ], comprLength )
223
220
data [3 ] = mc .compressSequence
224
-
225
- // this value is never greater than maxPayloadLength
226
- data [4 ] = byte (0xff & uncompressedLen )
227
- data [5 ] = byte (0xff & (uncompressedLen >> 8 ))
228
- data [6 ] = byte (0xff & (uncompressedLen >> 16 ))
221
+ putUint24 (data [4 :7 ], uncompressedLen )
229
222
230
223
if _ , err := mc .netConn .Write (data ); err != nil {
231
224
mc .log ("writing compressed packet:" , err )
0 commit comments