/* * Lilith - a log event viewer. * Copyright (C) 2007-2017 Joern Huxhorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.huxhorn.lilith.eventhandlers; import de.huxhorn.lilith.data.eventsource.EventWrapper; import de.huxhorn.lilith.data.eventsource.SourceIdentifier; import de.huxhorn.lilith.engine.EventHandler; import de.huxhorn.lilith.engine.FileBufferFactory; import de.huxhorn.lilith.engine.SourceManager; import de.huxhorn.lilith.engine.impl.EventSourceImpl; import de.huxhorn.sulky.buffers.FileBuffer; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FileSplitterEventHandler<T extends Serializable> implements EventHandler<T> { private final Logger logger = LoggerFactory.getLogger(FileSplitterEventHandler.class); private FileBufferFactory<T> fileBufferFactory; private ConcurrentMap<SourceIdentifier, FileBuffer<EventWrapper<T>>> fileBuffers; private SourceManager<T> sourceManager; public FileSplitterEventHandler(FileBufferFactory<T> fileBufferFactory, SourceManager<T> sourceManager) { this.fileBufferFactory = fileBufferFactory; fileBuffers = new ConcurrentHashMap<>(); this.sourceManager = sourceManager; } public void handle(List<EventWrapper<T>> events) { if(events == null || events.isEmpty()) { return; } Map<SourceIdentifier, List<EventWrapper<T>>> splitEvents = new HashMap<>(); for(EventWrapper<T> wrapper : events) { SourceIdentifier si = wrapper.getSourceIdentifier(); List<EventWrapper<T>> sourceList = splitEvents.get(si); if(sourceList == null) { sourceList = new ArrayList<>(); splitEvents.put(si, sourceList); } sourceList.add(wrapper); } if(logger.isInfoEnabled()) logger.info("Split {} events to {} sources.", events.size(), splitEvents.size()); for(Map.Entry<SourceIdentifier, List<EventWrapper<T>>> entry : splitEvents.entrySet()) { SourceIdentifier si = entry.getKey(); List<EventWrapper<T>> value = entry.getValue(); int valueCount = value.size(); // we know that valueCount is > 0 because otherwise it wouldn't exist. EventWrapper<T> lastEvent = value.get(valueCount - 1); boolean close = lastEvent.getEvent() == null; // resolveBuffer is also creating the view FileBuffer<EventWrapper<T>> buffer = resolveBuffer(si); buffer.addAll(value); if (logger.isInfoEnabled()) logger.info("Wrote {} events for source '{}'.", valueCount, si); if(close) { if(sourceManager != null) { sourceManager.removeSource(si); } File activeFile = fileBufferFactory.getLogFileFactory().getActiveFile(si); if(activeFile.delete()) { if(logger.isDebugEnabled()) logger.debug("Deleted active file {}.", activeFile.getAbsolutePath()); } fileBuffers.remove(si); } } } private FileBuffer<EventWrapper<T>> resolveBuffer(SourceIdentifier si) { FileBuffer<EventWrapper<T>> result = fileBuffers.get(si); if(result == null) { result = fileBufferFactory.createActiveBuffer(si); FileBuffer<EventWrapper<T>> contained = fileBuffers.putIfAbsent(si, result); if(contained != null) { result = contained; } else if(sourceManager != null) { sourceManager.addSource(new EventSourceImpl<>(si, result, false)); } } return result; } }