id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc	due_date
66	mongo硬缓存GZIP数据存取异常	huangxianduan	huangxianduan	"== 异常信息 ==
[08-30 10:38:42.841] 2011-08-30 10:38:42,841 [http-app-a-8081-5887$1521484495] ERROR cn.com.pconline.core.r.MongoRClientHelper  - [M
ongoRClientHelper] get cache:http://pdlib.pconline.com.cn/product/service2011/product_forum.jsp?pid=431809&style=1&time=7200 fail,me
ssage:java.io.IOException: '''Not in GZIP format'''
定位是R存/取mongo硬缓存时对较长的数据做GZIP压缩/解压有问题
== 排查及解决 ==
1. 测试R写硬缓存数据GZIP压缩是否有问题（报价前台是要求内容超过1024个字），测试GZIP压缩是没有问题的。
2. 测试R读取硬缓存GZIP数据解压是否有问题（mongo中保存了内容有保存了是否是压缩状态），测试如果数据标识了是GZIP的，读取解压也正常。
3. 怀疑是不是GZIP的API有bug呢，连续的用1做GZIP压缩写到mongo中，再用2解压读取出来，也是没有问题的。
4. 对单条数据进行多次的压缩和解压测试，每次内容不一样，有时长有时短，这个偶尔会重现异常，有些眉目了，怀疑是特殊字符的问题，但用报错的内容重新压缩再读取又没问题了，还是悲剧，不能定位到问题在哪。
5. 实在没办法，还是返回头仔细检查代码的写入和读取的判断是否一致，最后在代码上发现了写的判断有问题，代码如下：
{{{
#!java
public void setContent(byte[] content) {
	if (content != null){
		if(content.length > ZIP_SIZE) {//内容长度大于1024，请注意并没有else
			ByteArrayOutputStream bos = null;
			GZIPOutputStream gzip = null;
			try {
				bos = new ByteArrayOutputStream();
				gzip = new GZIPOutputStream(bos);
				gzip.write(content);
				gzip.flush();
				gzip.finish();
				gzip.close();
				bos.flush();
				content = bos.toByteArray();
				this.zip = true;//压缩，保存到数据库做标记
			} catch (IOException e) {
				e.printStackTrace();
				this.zip = false;
			} finally {
				try {
					if (bos != null) {
						bos.close();
					}
				} catch (IOException e) {
				}
			}
		}//为什么没有else呢？？？
		this.size = content.length;
	}
	this.content = content;
}
再来看看读取的方法
public byte[] getContent() {
	if (!zip) {
		return content;
	} else {//只要数据库标识是GZIP的就用GZIP解压读取
		byte[] result = null;
		ByteArrayInputStream bis = null;
		GZIPInputStream gzip = null;
		ByteArrayOutputStream baos = null;
		try {
			bis = new ByteArrayInputStream(content);
			gzip = new GZIPInputStream(bis);
			byte[] buf = new byte[1024];
			int num = -1;
			baos = new ByteArrayOutputStream();
			while ((num = gzip.read(buf, 0, buf.length)) != -1) {
				baos.write(buf, 0, num);
			}
			baos.flush();
			result = baos.toByteArray();
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		} finally {
			try {
				if (gzip != null) {
					gzip.close();
				}
				if (bis != null) {
					bis.close();
				}
				if (baos != null) {
					baos.close();
				}
			} catch (Exception e) {
			}
		}
		return result;
	}
}
}}}
- 问题很明显了，当第一次写入的数据长度大于1024的以GZIP格式写入，但第二次再更新写入是数据长度小于1024是却没有改变GZIP的状态，这样导致读取是还是当做GZIP格式来解压读取，肯定是会报格式不对的异常的。
"	Bug	new	major		报价库	报价库4.0		GZIP		15/11/2011
