package com.sogou.qadev.service.cynthia.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.xml.transform.TransformerException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.sogou.qadev.service.cynthia.bean.Filter;
import com.sogou.qadev.service.cynthia.bean.UUID;
import com.sogou.qadev.service.cynthia.factory.DataAccessFactory;
import com.sogou.qadev.service.cynthia.service.DataAccessSession;
import com.sogou.qadev.service.cynthia.service.DbPoolConnection;
import com.sogou.qadev.service.cynthia.service.impl.DataFilterMemory;
import com.sogou.qadev.service.cynthia.util.CynthiaUtil;
import com.sogou.qadev.service.cynthia.util.XMLUtil;
/**
* @description:new old data db processor
* @author:liming
* @mail:liming@sogou-inc.com
* @date:2014-5-6 下午5:46:39
* @version:v1.0
*/
public class NewDataNotifyAccessSessionMySQL
{
private DataAccessSession das = null;
private class FilterDataQueryWorker implements Runnable
{
private List<UUID> filterIdList;
private Map<UUID, Integer> filterDataCountMap;
private String username;
private CountDownLatch countDown;
public FilterDataQueryWorker(List<UUID> filterIdList, Map<UUID, Integer> filterDataCountMap , String username , CountDownLatch countDown) {
super();
this.filterIdList = filterIdList;
this.filterDataCountMap = filterDataCountMap;
this.username = username;
this.countDown = countDown;
}
public void run(){
while (true) {
UUID newfilterId = null;
int filterCount = 0;
synchronized (filterIdList) {
if (filterIdList.size() == 0) {
break;
}
newfilterId = filterIdList.remove(0);
}
if (newfilterId != null) {
try {
filterCount = getFilterCount(newfilterId, username);
} catch (TransformerException e) {
e.printStackTrace();
}
}
synchronized (filterIdList) {
filterDataCountMap.put(newfilterId, filterCount);
}
}
countDown.countDown();
}
}
private static ExecutorService threadPool = null;
public static ExecutorService getThreadPool(int threadCount)
{
if(threadPool == null)
threadPool = Executors.newFixedThreadPool(threadCount);
return threadPool;
}
public NewDataNotifyAccessSessionMySQL(DataAccessSession das)
{
super();
this.das = das;
}
public String getNewTaskIdsByFilterAndUser(UUID[] filterIdArray, String username)
{
Map<UUID, Set<String>> filterDataMap = getFilterNewOldTasks(filterIdArray, username); //过滤器对应旧数据集合
String retXML = turnFilterDataMapToXMLForQuery(filterDataMap, username);
return retXML;
}
public String cleanNewTagByTaskIds(UUID filterId, UUID[] taskIdArray, String username)
{
insertFilterUserTasks(filterId, username, taskIdArray);
return "success";
}
protected String turnFilterDataMapToXMLForQuery(Map<UUID, Set<String>> filterDataMap, String username)
{
StringBuffer xmlBuffer = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
xmlBuffer.append("<filters>");
Map<UUID, Integer> filterCountMap = new HashMap<UUID, Integer>();
List<UUID> allFilterList = new ArrayList<UUID>(filterDataMap.keySet());
//开启线程数
int threadCount = filterDataMap.keySet().size() > 20 ? 5 : 2;
CountDownLatch countDown = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(new FilterDataQueryWorker(allFilterList , filterCountMap , username , countDown)).start();
}
try{
countDown.await();
}
catch(Exception e){
e.printStackTrace();
}
for(UUID filterId : filterDataMap.keySet())
{
xmlBuffer.append("<filter id=\"").append(filterId.getValue()).append("\"");
int totalCount = 0;
int oldTotal = 0;
Set<String> oldSet = filterDataMap.get(filterId);
oldTotal = oldSet.size();
totalCount = filterCountMap.get(filterId);
xmlBuffer.append(" oldAccount=\"").append(oldTotal).append("\"");
int newCount = totalCount - oldTotal ;
if (newCount < 0) {
newCount = 0;
}
xmlBuffer.append(" newAccount=\"").append(newCount).append("\"");
xmlBuffer.append(" totalAccount=\"").append(totalCount).append("\"");
xmlBuffer.append(" maxAccount=\"").append(totalCount).append("\">");
StringBuffer oldBuffer = new StringBuffer(500);
for(String taskId : oldSet)
{
oldBuffer.append(oldBuffer.length() > 0 ? "," : "").append(taskId);
}
xmlBuffer.append("<oldTasks>").append(oldBuffer).append("</oldTasks>");
xmlBuffer.append("</filter>");
}
xmlBuffer.append("</filters>");
return xmlBuffer.toString();
}
/**
* @Title: getFilterCount
* @Description: 查询过滤器数据总量
* @param filterId
* @param username
* @return
* @throws TransformerException
* @return: int
*/
private int getFilterCount(UUID filterId , String username) throws TransformerException{
Set<String> querySpeFieldSet = new HashSet<String>();
Filter filter = das.queryFilter(filterId);
if (filter == null || filter.getXml() == null || ("").equals(filter.getXml()) ) {
return 0 ;
}
Document filterXMLDoc = null;
try{
filterXMLDoc = XMLUtil.string2Document(filter.getXml(), "UTF-8");
}catch(Exception e){
System.out.println("filter parse error , filter id :" + filter.getId().getValue());
}
if(filterXMLDoc == null){
return 0;
}
Node queryNode = XMLUtil.getSingleNode(filterXMLDoc, "query");
Node templateTypeNode = XMLUtil.getSingleNode(queryNode, "templateType");
String templateTypeIdStr = XMLUtil.getAttribute(templateTypeNode, "id");
if(templateTypeIdStr.equals("$current_template_type$")){
Node envNode = XMLUtil.getSingleNode(queryNode, "env");
Node currentUserNode = XMLUtil.getSingleNode(envNode, "current_user");
if(currentUserNode == null){
currentUserNode = filterXMLDoc.createElement("current_user");
envNode.appendChild(currentUserNode);
}
currentUserNode.setTextContent(username);
}
int totalCount = 0;
querySpeFieldSet.add("id");
String sql = DataFilterMemory.getFilterSql(XMLUtil.document2String(filterXMLDoc, "UTF-8"), querySpeFieldSet ,null);
sql = CynthiaUtil.cancelGroupOrder(sql);
sql = sql.replace("as id", "");
String[] allSQLArray = sql.split("union");
for (String sqlStr : allSQLArray) {
sqlStr = sqlStr.trim();
StringBuffer sqlBuffer = new StringBuffer();
sqlBuffer.append("select count(").append(sqlStr.substring(sqlStr.indexOf("select") +6, sqlStr.indexOf("from"))).append(" ) ").append(sqlStr.substring(sqlStr.indexOf("from")));
if (filterId.getValue().equals("119695")) {
System.out.println("待处理 filter count sql:" + sqlBuffer.toString());
}
totalCount += DbPoolConnection.getInstance().getCountOfSQL(sqlBuffer.toString());
}
return totalCount;
}
public Map<UUID, Set<String>> getFilterNewOldTasks(UUID[] filterIdArray, String username)
{
Map<UUID, Set<String>> retMap = new HashMap<UUID, Set<String>> ();
for (UUID filterId : filterIdArray) {
retMap.put(filterId, new HashSet<String>());
}
Connection conn = null;
Statement stm = null;
ResultSet rst = null;
try
{
conn = DbPoolConnection.getInstance().getReadConnection();
stm = conn.createStatement();
StringBuffer sqlStrb = new StringBuffer();
sqlStrb.append("SELECT filter_id, old_id FROM user_new_data");
sqlStrb.append(" WHERE user = '").append(username).append("'");
if(filterIdArray != null && filterIdArray.length > 0)
{
sqlStrb.append(" AND (");
for(int i = 0; i < filterIdArray.length; i++)
{
if(i > 0)
sqlStrb.append(" OR");
sqlStrb.append(" filter_id = '").append(filterIdArray[i].getValue()).append("'");
}
sqlStrb.append(" )");
}
rst = stm.executeQuery(sqlStrb.toString());
while(rst.next())
{
UUID filterId = DataAccessFactory.getInstance().createUUID(rst.getString("filter_id"));
String old_id = rst.getString("old_id");
if(old_id != null)
retMap.get(filterId).add(old_id);
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
DbPoolConnection.getInstance().closeAll(rst, stm, conn);
}
return retMap;
}
public void insertFilterUserTasks(UUID filterId, String username, UUID[] oldIdArray)
{
PreparedStatement pstm = null;
Connection conn = null;
try
{
conn = DbPoolConnection.getInstance().getConnection();
for (UUID uuid : oldIdArray) {
pstm = conn.prepareStatement("insert ignore into user_new_data"
+ " SET filter_id = ?"
+ ", user = ?"
+ ", old_id = ?");
pstm.setString(1, filterId.getValue());
pstm.setString(2, username);
pstm.setString(3, uuid.getValue());
pstm.executeUpdate();
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
DbPoolConnection.getInstance().closeStatment(pstm);
DbPoolConnection.getInstance().closeConn(conn);
}
}
public void deleteFilterUserTasks(UUID dataId)
{
Connection conn = null;
Statement stm = null;
try
{
conn = DbPoolConnection.getInstance().getConnection();
stm = conn.createStatement();
stm.executeUpdate("DELETE FROM user_new_data WHERE old_id = '" + dataId.getValue() + "'");
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
DbPoolConnection.getInstance().closeStatment(stm);
DbPoolConnection.getInstance().closeConn(conn);
}
}
}