/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.systemservices.impl.logsvc.merger; import java.io.IOException; import java.util.*; 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.stream.LogStream; import com.emc.storageos.systemservices.impl.logsvc.util.LogUtil; import com.emc.vipr.model.sys.logging.LogRequest; /** * This class is responsible to read one line from each logstream and sort them based on timestamp. * This is done on per host basis. * */ public abstract class AbstractLogStreamMerger { protected LogStream[] logStreamList; protected LogMessage[] logHeads; protected LogRequest request; protected LogStatusInfo status = new LogStatusInfo(); private Set<Integer> finishedList = new HashSet<>(); private boolean finished = false; private AtomicLong logCounter = new AtomicLong(0); private int finishedCount = 0; // finished streams private long prevLogTime; // defaults to 0 // Logger reference. private static final Logger logger = LoggerFactory.getLogger(AbstractLogStreamMerger.class); /** * This is the routine handles the request, sends back the response(outputstream) * * @throws java.io.IOException * @throws org.apache.commons.compress.compressors.CompressorException */ public LogMessage readNextMergedLogMessage() throws IOException, CompressorException { LogMessage oldestResult = null; LogMessage oldest = null; int index = -1; if (finishedCount == logStreamList.length) { setFinished(true); return null; } // poll the streams to get the oldest log message for (int i = 0; i < logStreamList.length; i++) { if (finishedList.contains(i)) { continue; } if (logHeads[i] == null) { logHeads[i] = logStreamList[i].readNextLogMessage(); if (logHeads[i] == null) { // finished addFinishedStream(i); finishedCount++; logger.debug("merger counter={}", logCounter); continue; } } // logs[i] should not be null now if (oldest == null || logHeads[i].getTime() < oldest.getTime()) { oldest = logHeads[i]; index = i; } } if (oldest != null) { logHeads[index] = null; logCounter.addAndGet(1); if (LogUtil.permitCurrentLog(request.getMaxCount(), logCounter.get(), oldest.getTime(), prevLogTime)) { oldestResult = oldest; } prevLogTime = oldest.getTime(); } return oldestResult; } protected void addFinishedStream(int i) { finishedList.add(i); } public LogRequest getRequest() { return request; } public void setRequest(LogRequest request) { this.request = request; } public boolean isFinished() { return finished; } public void setFinished(boolean finished) { this.finished = finished; } public long getLogCount() { return this.logCounter.get(); } public LogStatusInfo getStatus() { return this.status; } public void clearStatus() { this.status.clear(); } }