package com.ycsoft.report.query.redis;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import com.ycsoft.commons.exception.ReportException;
import com.ycsoft.report.commons.CacheInput;
import com.ycsoft.report.commons.CacheOutput;
import com.ycsoft.report.commons.ReportConstants;
import com.ycsoft.report.commons.SerializeUtil;
import com.ycsoft.report.commons.StringUtil;
import com.ycsoft.report.commons.SystemConfig;
import com.ycsoft.report.dao.redis.JedisDao;
import com.ycsoft.report.query.QueryResult;
public class CommonRedisCache implements QRRedisCache {
private int page_row_max=1000;
private static final String KEY_BEAN="bean:";
private static final String KEY_BASE="base:";
private static final String KEY_BEAN_SQL="sql";
private static final String KEY_BEAN_QUERYID="query_id";
private static final String KEY_BEAN_HEAD="head";
private static final String KEY_BEAN_ROWS="rows";
/**
* 缓存基础键值
*/
private String base_cache_key="";
private QueryResult qr=null;
private JedisDao jedisDao=null;
public CommonRedisCache(QueryResult qr,JedisDao jedisDao) throws ReportException{
this(qr,ReportConstants.cache_page_row_max,jedisDao);
}
private CommonRedisCache(QueryResult qr,int page_row_max,JedisDao jedisDao) throws ReportException{
this.jedisDao=jedisDao;
if(this.page_row_max>0){
this.page_row_max=page_row_max;
}
this.qr=qr;
if(ReportConstants.DATABASETYPE_REALTIME
.equals(SystemConfig.getDatabaseMap().get(qr.getDatabase()).getType())){
this.base_cache_key=this.qr.getQueryId();
}else{
if(qr.getQRSHA()==null){
throw new ReportException("历史数据表 QRSHA is null");
}
this.base_cache_key=qr.getQRSHA();
}
}
/**
*
*/
public void cacheQueryId(String query_id) throws ReportException {
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
jedisDao.hset(bf.toString().getBytes(), KEY_BEAN_QUERYID.getBytes(), query_id.getBytes());
}
/**
* 提取query_id
*/
public String extractQueryId() throws ReportException {
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
byte[] queryid= jedisDao.hget(bf.toString().getBytes(), KEY_BEAN_QUERYID.getBytes());
if(queryid==null||queryid.length==0)
return null;
else
return new String(queryid);
}
/**
* 行数
*/
public void cacheRows(Integer rows) throws ReportException {
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
jedisDao.hset(bf.toString().getBytes(), KEY_BEAN_ROWS.getBytes(), rows.toString().getBytes());
}
/**
* 行数
*/
public Integer extractRows() throws ReportException {
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
byte[] rows= jedisDao.hget(bf.toString().getBytes(), KEY_BEAN_ROWS.getBytes());
if(rows==null||rows.length==0)
return null;
else
return Integer.valueOf(new String(rows));
}
/**
* 存查询sql
*/
public void cacheQuerySql(String sql) throws ReportException {
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
jedisDao.hset(bf.toString().getBytes(), KEY_BEAN_SQL.getBytes(), StringUtil.compressZip(sql.getBytes()));
}
/**
* 提取查询sql
*/
public String extractQuerySql() throws ReportException {
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
byte[] sql= StringUtil.compressZip(jedisDao.hget(bf.toString().getBytes(), KEY_BEAN_SQL.getBytes()));
if(sql==null)
return null;
else
return new String(sql);
}
/**
* 缓存表头
*/
public void cacheHead(Serializable head) throws ReportException {
byte[] h= SerializeUtil.serialize(head);
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
jedisDao.hset(bf.toString().getBytes(), KEY_BEAN_HEAD.getBytes(), h);
}
/**
* 提取表头
*/
public Serializable extractHead() throws ReportException {
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BEAN).append(this.base_cache_key);
byte[] h= jedisDao.hget(bf.toString().getBytes(), KEY_BEAN_HEAD.getBytes());
if(h==null||h.length==0)
return null;
else
return SerializeUtil.unserialize(h);
}
/**
* 提取结果集对应键值
* @return
*/
public String getContextKey(int page_idx){
StringBuilder bf=new StringBuilder();
bf.append(this.qr.getRepId()).append(KEY_BASE)
.append(this.base_cache_key).append("_").append(page_idx);
return bf.toString();
}
private int i=0;
private ArrayList<Serializable> page=null;
private int page_index=1;
/**
* row=null 表示写入结束
* @param row
* @throws ReportException
*/
public void cacheContext(Serializable row) throws ReportException {
if(page==null){
page=new ArrayList<Serializable>(this.page_row_max);
}
if(i==this.page_row_max||(row==null&&page!=null&&page.size()>0)){
//1000行压缩后写入redis缓存
byte[] value= StringUtil.compressZip(SerializeUtil.serialize(page));
jedisDao.set(getContextKey(this.page_index).getBytes(), value);
//重新计数
i=0;
//页码加1
page_index++;
if(row!=null) page.clear();
}else{
page.add(row);
i++;
}
}
/**
* 提取内容
* @throws ReportException
*/
public Serializable extractContextPage(int page_index) throws ReportException {
byte[] value=jedisDao.get(getContextKey(page_index).getBytes());
if(value==null)
return null;
else
return SerializeUtil.unserialize(StringUtil.uncompressZip(value));
}
public int getPage_index() {
return page_index;
}
public CacheInput getRedisCacheInput() {
return new RedisCacheInput();
}
/**
* 从redis缓存中读取数据
*/
class RedisCacheInput implements CacheInput{
private int page_idx=0;
private ArrayList<Serializable> page=new ArrayList<Serializable>(page_row_max);
private int row_idx=0;
public RedisCacheInput(){
page_idx=0;
}
public void close() throws Exception {
if(page!=null) page.clear();
}
public Object readHead() throws ReportException{
return extractHead();
}
public Object readObject() throws ReportException {
if(row_idx>=page.size()){
page_idx++;
page=(ArrayList<Serializable>) extractContextPage(page_idx);
if(page==null||page.size()==0){
return null;
}
row_idx=0;
}
Object row=page.get(row_idx);
row_idx++;
return row;
}
}
public CacheOutput getRedisCacheOutput() {
return new RedisCacheOutput();
}
/**
* 输出到redis缓存中
*/
class RedisCacheOutput implements CacheOutput{
public void writeHead(Object obj) throws IOException, ReportException {
cacheHead((Serializable)obj);
}
public void writeObject(Object obj) throws IOException, ReportException {
cacheContext((Serializable)obj);
}
public void close() throws IOException, ReportException {
cacheContext(null);
}
}
}