[Lilith-devel] SF.net SVN: lilith:[171] trunk/lilith/src/main/java/de/huxhorn/lilith
Brought to you by:
huxhorn
From: <hu...@us...> - 2009-02-15 13:14:50
|
Revision: 171 http://lilith.svn.sourceforge.net/lilith/?rev=171&view=rev Author: huxhorn Date: 2009-02-15 13:14:46 +0000 (Sun, 15 Feb 2009) Log Message: ----------- Work on making filtered views use tasks. See ticket:33. Filtered views aren't automatically closed yet. Modified Paths: -------------- trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java Added Paths: ----------- trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/CallableMetaData.java trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/FilteringCallable.java Modified: trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java 2009-02-15 04:38:58 UTC (rev 170) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/buffers/FilteringBuffer.java 2009-02-15 13:14:46 UTC (rev 171) @@ -1,5 +1,6 @@ package de.huxhorn.lilith.buffers; +import de.huxhorn.lilith.swing.callables.FilteringCallable; import de.huxhorn.sulky.buffers.BasicBufferIterator; import de.huxhorn.sulky.buffers.Buffer; import de.huxhorn.sulky.buffers.DisposeOperation; @@ -11,10 +12,13 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class FilteringBuffer<E> implements Buffer<E>, DisposeOperation { + private final Logger logger = LoggerFactory.getLogger(FilteringCallable.class); + public static <E> Buffer<E> resolveSourceBuffer(Buffer<E> buffer) { for(; ;) @@ -29,18 +33,17 @@ private Buffer<E> sourceBuffer; private Condition condition; + private ReentrantReadWriteLock indicesLock; private final List<Long> filteredIndices; private boolean disposed; public FilteringBuffer(Buffer<E> sourceBuffer, Condition condition) { + this.indicesLock = new ReentrantReadWriteLock(); this.sourceBuffer = sourceBuffer; this.condition = condition; this.filteredIndices = new ArrayList<Long>(); this.disposed = false; - Thread t = new Thread(new FilterUpdateRunnable(1000)); - t.setDaemon(true); - t.start(); } public E get(long index) @@ -56,24 +59,71 @@ public long getSourceIndex(long index) { long realIndex = -1; - synchronized(filteredIndices) + //synchronized(filteredIndices) + ReentrantReadWriteLock.ReadLock lock = indicesLock.readLock(); + lock.lock(); + try { if(index >= 0 && index < filteredIndices.size()) { realIndex = filteredIndices.get((int) index); } } + finally + { + lock.unlock(); + } return realIndex; } public long getSize() { - synchronized(filteredIndices) + //synchronized(filteredIndices) + ReentrantReadWriteLock.ReadLock lock = indicesLock.readLock(); + lock.lock(); + try { return filteredIndices.size(); } + finally + { + lock.unlock(); + } } + public void addFilteredIndex(long index) + { + long size = sourceBuffer.getSize(); + if(index < 0 || index >= sourceBuffer.getSize()) + { + if(logger.isInfoEnabled()) logger.info("Invalid filtered index {} (size={})!", index, size); + } + ReentrantReadWriteLock.WriteLock lock = indicesLock.writeLock(); + lock.lock(); + try + { + filteredIndices.add(index); + } + finally + { + lock.unlock(); + } + } + + public void clearFilteredIndices() + { + ReentrantReadWriteLock.WriteLock lock = indicesLock.writeLock(); + lock.lock(); + try + { + filteredIndices.clear(); + } + finally + { + lock.unlock(); + } + } + public Iterator<E> iterator() { return new BasicBufferIterator<E>(this); @@ -98,75 +148,4 @@ { return disposed; } - - private class FilterUpdateRunnable - implements Runnable - { - private final Logger logger = LoggerFactory.getLogger(FilterUpdateRunnable.class); - - private int filterDelay; - private long lastFilteredElement; - - public FilterUpdateRunnable(int filterDelay) - { - this.filterDelay = filterDelay; - } - - public void run() - { - for(; ;) - { - if(disposed) - { - break; - } - long currentSize = sourceBuffer.getSize(); - long filterStartIndex = lastFilteredElement; - if(currentSize < lastFilteredElement) - { - filterStartIndex = 0; - synchronized(filteredIndices) - { - filteredIndices.clear(); - } - } - - if(currentSize != lastFilteredElement + 1) - { - //List<Long> newIndices=new ArrayList<Long>(); - for(long i = filterStartIndex; i < currentSize; i++) - { - if(disposed) - { - break; - } - E current = sourceBuffer.get(i); - if(current != null) - { - if(condition != null && condition.isTrue(current)) - { - synchronized(filteredIndices) - { - filteredIndices.add(i); - if(logger.isDebugEnabled()) logger.debug("Added index: {}", i); - } - } - } - lastFilteredElement = i; - } - //if(logger.isInfoEnabled()) logger.info("Added {} indices.", newIndices.size()); - } - try - { - Thread.sleep(filterDelay); - } - catch(InterruptedException e) - { - if(logger.isDebugEnabled()) logger.debug("Interrupted...", e); - return; - } - } - if(logger.isDebugEnabled()) logger.debug("Runnable finished."); - } - } } Modified: trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java 2009-02-15 04:38:58 UTC (rev 170) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/swing/EventWrapperViewPanel.java 2009-02-15 13:14:46 UTC (rev 171) @@ -30,13 +30,14 @@ import de.huxhorn.lilith.data.logging.LoggingEvent; import de.huxhorn.lilith.engine.EventSource; import de.huxhorn.lilith.engine.impl.EventSourceImpl; +import de.huxhorn.lilith.swing.callables.CallableMetaData; +import de.huxhorn.lilith.swing.callables.FilteringCallable; import de.huxhorn.lilith.swing.linklistener.StackTraceElementLinkListener; import de.huxhorn.lilith.swing.preferences.SavedCondition; import de.huxhorn.lilith.swing.table.EventWrapperViewTable; import de.huxhorn.lilith.swing.table.model.EventWrapperTableModel; import de.huxhorn.sulky.buffers.Buffer; import de.huxhorn.sulky.buffers.DisposeOperation; -import de.huxhorn.sulky.buffers.FileBuffer; import de.huxhorn.sulky.conditions.And; import de.huxhorn.sulky.conditions.Condition; import de.huxhorn.sulky.conditions.Not; @@ -76,7 +77,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; @@ -145,10 +145,6 @@ private XHTMLPanel messagePane; private XhtmlNamespaceHandler xhtmlNamespaceHandler; private EventWrapper<T> selectedEvent; - private static final String FIND_TASK_META_CONDITION = "Condition"; - private static final String FIND_TASK_META_EVENT_SOURCE = "EventSource"; - private static final String FIND_TASK_META_START_ROW = "StartRow"; - private static final String FIND_TASK_META_DATA_FILE = "DataFile"; public EventWrapperViewPanel(MainFrame mainFrame, EventSource<T> eventSource) @@ -1145,7 +1141,14 @@ Condition filter = getCombinedCondition(); if(filter != null && !filter.equals(previousClone)) { - Buffer<EventWrapper<T>> filteredBuffer = new FilteringBuffer<EventWrapper<T>>(buffer, filter); + FilteringBuffer<EventWrapper<T>> filteredBuffer = new FilteringBuffer<EventWrapper<T>>(buffer, filter); + FilteringCallable<EventWrapper<T>> callable = new FilteringCallable<EventWrapper<T>>(filteredBuffer, 500); + // TODO: register callable somewhere + Map<String, String> metaData = CallableMetaData.createFilteringMetaData(filter, eventSource); + + taskManager.startTask(callable, "Filtering", "Filtering " + metaData + .get(CallableMetaData.FIND_TASK_META_SOURCE_IDENTIFIER) + + " on condition " + metaData.get(CallableMetaData.FIND_TASK_META_CONDITION) + ".", metaData); return new EventSourceImpl<T>(eventSource.getSourceIdentifier(), filteredBuffer, filter, eventSource.isGlobal()); } return null; @@ -1673,33 +1676,12 @@ private void executeFind(Callable<Long> callable, String name, int currentRow, Condition condition) { - String conditionStr = condition.toString(); - String eventSourceStr = null; - Buffer<EventWrapper<T>> buffer = null; - if(eventSource != null) - { - eventSourceStr = eventSource.toString(); - buffer = eventSource.getBuffer(); - } + Map<String, String> metaData = CallableMetaData.createFindMetaData(condition, eventSource, currentRow); - String description = "Executing '" + name + "' for condition " + conditionStr + " on " + eventSourceStr + " starting at row " + currentRow + "."; - Map<String, String> metaData = new HashMap<String, String>(); - metaData.put(FIND_TASK_META_CONDITION, conditionStr); - metaData.put(FIND_TASK_META_START_ROW, "" + currentRow); - if(eventSourceStr != null) - { - metaData.put(FIND_TASK_META_EVENT_SOURCE, eventSourceStr); - } - Buffer<EventWrapper<T>> sourceBuffer = FilteringBuffer.resolveSourceBuffer(buffer); - if(sourceBuffer instanceof FileBuffer) - { - FileBuffer<EventWrapper<T>> fileBuffer = (FileBuffer<EventWrapper<T>>) sourceBuffer; - File file = fileBuffer.getDataFile(); - if(file != null) - { - metaData.put(FIND_TASK_META_DATA_FILE, file.getAbsolutePath()); - } - } + String description = "Executing '" + name + "' for condition " + metaData + .get(CallableMetaData.FIND_TASK_META_CONDITION) + + " on " + metaData + .get(CallableMetaData.FIND_TASK_META_SOURCE_IDENTIFIER) + " starting at row " + currentRow + "."; enableFindComponents(false); findResultListener.setCallable(callable); Added: trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/CallableMetaData.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/CallableMetaData.java (rev 0) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/CallableMetaData.java 2009-02-15 13:14:46 UTC (rev 171) @@ -0,0 +1,110 @@ +/* + * Lilith - a log event viewer. + * Copyright (C) 2007-2009 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.swing.callables; + +import de.huxhorn.lilith.buffers.FilteringBuffer; +import de.huxhorn.lilith.data.eventsource.EventWrapper; +import de.huxhorn.lilith.data.eventsource.SourceIdentifier; +import de.huxhorn.lilith.engine.EventSource; +import de.huxhorn.sulky.buffers.Buffer; +import de.huxhorn.sulky.buffers.FileBuffer; +import de.huxhorn.sulky.conditions.Condition; + +import java.io.File; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class CallableMetaData +{ + public static final String FIND_TASK_META_CONDITION = "Condition"; + public static final String FIND_TASK_META_SOURCE_IDENTIFIER = "SourceIdentifier"; + public static final String FIND_TASK_META_START_ROW = "StartRow"; + public static final String FIND_TASK_META_DATA_FILE = "DataFile"; + + public static <T extends Serializable> Map<String, String> createFindMetaData(Condition condition, EventSource<T> eventSource, int startRow) + { + String conditionStr = null; + if(condition != null) + { + conditionStr = condition.toString(); + } + Buffer<EventWrapper<T>> buffer = null; + String sourceIdentifierStr = null; + if(eventSource != null) + { + buffer = eventSource.getBuffer(); + SourceIdentifier si = eventSource.getSourceIdentifier(); + if(si != null) + { + sourceIdentifierStr = si.toString(); + } + } + Map<String, String> metaData = new HashMap<String, String>(); + metaData.put(FIND_TASK_META_CONDITION, conditionStr); + metaData.put(FIND_TASK_META_START_ROW, "" + startRow); + if(sourceIdentifierStr != null) + { + metaData.put(FIND_TASK_META_SOURCE_IDENTIFIER, sourceIdentifierStr); + } + resolveDataFile(metaData, buffer); + return metaData; + } + + public static <T extends Serializable> Map<String, String> createFilteringMetaData(Condition condition, EventSource<T> eventSource) + { + String conditionStr = null; + if(condition != null) + { + conditionStr = condition.toString(); + } + Buffer<EventWrapper<T>> buffer = null; + String sourceIdentifierStr = null; + if(eventSource != null) + { + buffer = eventSource.getBuffer(); + SourceIdentifier si = eventSource.getSourceIdentifier(); + if(si != null) + { + sourceIdentifierStr = si.toString(); + } + } + Map<String, String> metaData = new HashMap<String, String>(); + metaData.put(FIND_TASK_META_CONDITION, conditionStr); + if(sourceIdentifierStr != null) + { + metaData.put(FIND_TASK_META_SOURCE_IDENTIFIER, sourceIdentifierStr); + } + resolveDataFile(metaData, buffer); + return metaData; + } + + private static <T extends Serializable> void resolveDataFile(Map<String, String> metaData, Buffer<EventWrapper<T>> buffer) + { + Buffer<EventWrapper<T>> sourceBuffer = FilteringBuffer.resolveSourceBuffer(buffer); + if(sourceBuffer instanceof FileBuffer) + { + FileBuffer<EventWrapper<T>> fileBuffer = (FileBuffer<EventWrapper<T>>) sourceBuffer; + File file = fileBuffer.getDataFile(); + if(file != null) + { + metaData.put(FIND_TASK_META_DATA_FILE, file.getAbsolutePath()); + } + } + } +} Added: trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/FilteringCallable.java =================================================================== --- trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/FilteringCallable.java (rev 0) +++ trunk/lilith/src/main/java/de/huxhorn/lilith/swing/callables/FilteringCallable.java 2009-02-15 13:14:46 UTC (rev 171) @@ -0,0 +1,107 @@ +/* + * Lilith - a log event viewer. + * Copyright (C) 2007-2009 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.swing.callables; + +import de.huxhorn.lilith.buffers.FilteringBuffer; +import de.huxhorn.sulky.buffers.Buffer; +import de.huxhorn.sulky.conditions.Condition; +import de.huxhorn.sulky.tasks.AbstractProgressingCallable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FilteringCallable<E> + extends AbstractProgressingCallable<Long> +{ + private final Logger logger = LoggerFactory.getLogger(FilteringCallable.class); + + private int filterDelay; + private long lastFilteredElement; + private FilteringBuffer<E> filteringBuffer; + + + public FilteringCallable(FilteringBuffer<E> filteringBuffer, int filterDelay) + { + this.filterDelay = filterDelay; + this.filteringBuffer = filteringBuffer; + } + + public void run() + { + if(logger.isDebugEnabled()) logger.debug("Runnable finished."); + } + + public Long call() + throws Exception + { + for(; ;) + { + Buffer<E> sourceBuffer = filteringBuffer.getSourceBuffer(); + Condition condition = filteringBuffer.getCondition(); + boolean disposed = filteringBuffer.isDisposed(); + if(disposed) + { + break; + } + long currentSize = sourceBuffer.getSize(); + long filterStartIndex = lastFilteredElement; + if(currentSize < lastFilteredElement) + { + filterStartIndex = 0; + filteringBuffer.clearFilteredIndices(); + } + + setNumberOfSteps(currentSize); + setCurrentStep(filterStartIndex); + + if(currentSize != lastFilteredElement + 1) + { + for(long i = filterStartIndex; i < currentSize; i++) + { + disposed = filteringBuffer.isDisposed(); + if(disposed) + { + break; + } + E current = sourceBuffer.get(i); + if(current != null) + { + if(condition != null && condition.isTrue(current)) + { + filteringBuffer.addFilteredIndex(i); + if(logger.isDebugEnabled()) logger.debug("Added index: {}", i); + } + } + setCurrentStep(i); + lastFilteredElement = i; + } + } + try + { + Thread.sleep(filterDelay); + } + catch(InterruptedException e) + { + if(logger.isDebugEnabled()) logger.debug("Interrupted...", e); + return lastFilteredElement; + } + } + if(logger.isDebugEnabled()) logger.debug("Callable finished."); + return lastFilteredElement; + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |