/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.systemservices.impl.logsvc.stream; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.compress.compressors.CompressorException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.systemservices.impl.logsvc.LogMessage; import com.emc.storageos.systemservices.impl.logsvc.LogStatusInfo; import com.emc.storageos.systemservices.impl.logsvc.util.LogUtil; import com.emc.vipr.model.sys.logging.LogRequest; public class LogFileStream implements LogStream { // Logger reference. private static final Logger logger = LoggerFactory.getLogger(LogFileStream.class); private final String basename; private final List<String> logPaths; private LogReader reader; private LogRequest request; private LogStatusInfo status; // number of logs get from LogReader private AtomicLong logCounter = new AtomicLong(0); // finished files number private AtomicInteger fileCounter = new AtomicInteger(0); // file size counter, sum up all read files private AtomicLong sizeCounter = new AtomicLong(0); // file size counter, sum up all read files private List<LogMessage> logs = new LinkedList<>(); // all logMessages which has the same timeStamp private LogMessage currentLog; // defaults to null private long prevLogTime; // defaults to 0 public LogFileStream(String basename, List<File> logFiles, LogRequest req, LogStatusInfo status) { logger.trace("LogFileStream()"); this.request = req; this.basename = basename; this.logPaths = setLogPaths(logFiles); reader = null; this.status = status; } /** * Set log files related to a service, sorted by last modification time. * * @param logFiles * @return list of log file paths for a given basename sorted by time * @throws IOException */ private List<String> setLogPaths(List<File> logFiles) { logger.trace("set path"); List<String> names = new ArrayList<String>(); try { names = LogUtil.fileNameWildCardSearch(logFiles, request.getStartTime(), request.getEndTime()); for (String name : names) { logger.debug("Found - " + name); } } catch (IOException e) { logger.error("IOException in setLogPaths:", e); } return names; } public List<String> getLogPaths() { return this.logPaths; } /** * Read log files one by one and, line by line from the data folder. * * @return * @throws IOException * @throws CompressorException */ @Override public LogMessage readNextLogMessage() { while (true) { if (fileCounter.get() >= logPaths.size()) { break; } // open new log file and new Reader if (reader == null) { String filePath = logPaths.get(fileCounter.get()); try { reader = new LogReader(filePath, request, status, basename); } catch (Exception e) { status.append(String.format("Failed to open log file %s", e.getMessage())); logger.error("Failed to generate log reader for {}", e.getMessage()); return null; } logger.debug("Reading file - " + filePath); File f = new File(filePath); sizeCounter.addAndGet(f.length()); } if (currentLog != null) { prevLogTime = currentLog.getTime(); } currentLog = reader.readNextLogMessage(); if (currentLog != null) { logCounter.incrementAndGet(); currentLog.setService(LogUtil.serviceToBytes(basename)); // we cannot determine until the current log message has been read out if (!LogUtil.permitCurrentLog(request.getMaxCount(), logCounter.get(), currentLog.getTime(), prevLogTime)) { break; } return currentLog; } else { reader = null; fileCounter.incrementAndGet(); } } return null; } public long getTotalLogCount() { return logCounter.get(); } public long getTotalSizeCount() { return sizeCounter.get(); } public int getFileCount() { return this.fileCounter.get(); } public LogRequest getRequest() { return request; } public void setRequest(LogRequest request) { this.request = request; } }