package com.bcxin.ins.aspect;

import com.bcxin.ins.core.entity.SysLog;
import com.bcxin.mybatisplus.toolkit.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;

/**
 * @author：huangzp
 * @date：2018/05/02 0002 15:49
 * @description：
 */
public class LogManager {

    private static Logger logger = LoggerFactory.getLogger(LogManager.class);

    //定义并发非阻塞线程安全双向Deque缓存队列，存储待入库的日志记录  JDk7新特性
    public static ConcurrentLinkedDeque<SysLog> logList = new ConcurrentLinkedDeque<SysLog>();

    /**
     * 新增日志到队列
     *
     * @param sysLog
     */
    public static void addLog(SysLog sysLog) {
        logList.add(sysLog);
    }

    /**
     * 去除并且删除记录
     * @return
     */
    private static SysLog deleteItem() {
        SysLog result = null;
        try {
            //取出并删除最前面的一条数据
            if(logList.size()>0){
                result = logList.remove();
            }else{
                logger.debug("ConcurrentLinkedDeque deleteItem fail: 队列暂无数据!");
            }
        } catch (Exception e) {
            logger.error("LogManager -> deleteItem(),error:"+e.getMessage());
            if(StringUtils.isEmpty(e.getMessage())||"null".equals(e.getMessage())){
                //非线程安全的可能这次进来list还有数据，但是在执行remove()的时候已经都被其它线程处理完了，这种情况就会跑这里
            }else{
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 每次执行500
     * @return
     */
    public static List<SysLog> getLogs(){
        List<SysLog> items = new ArrayList<SysLog>();
        while (true) {
            //从缓存中取出1条日志，但不从缓存中删除。用于检查队列中是否有数据
            SysLog item = logList.peek();
            if (item == null) {
                //item为null说明缓存中没有日志了，这时如果临时队列items中有记录，就可以批量入库了
                break;
            }
            if(items.size()==500){
                break;
            }
            //从缓存中取出并删除最前面的日志，如果无数据，在堵塞
            SysLog result = deleteItem();
            if(result != null){
                //将取出的记录放到临时队列中
                items.add(result);
            }
        }
        return items;
    }
}
