/*********************************************************************************** * * Copyright (c) 2014 Kamil Baczkowicz * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * * Kamil Baczkowicz - initial API and implementation and/or initial documentation * */ package pl.baczkowicz.spy.ui.storage; import pl.baczkowicz.spy.messages.FormattedMessage; import pl.baczkowicz.spy.ui.events.queuable.EventQueueManager; import pl.baczkowicz.spy.ui.events.queuable.ui.BrowseRemovedMessageEvent; import pl.baczkowicz.spy.ui.events.queuable.ui.TopicSummaryRemovedMessageEvent; import pl.baczkowicz.spy.utils.ThreadingUtils; /** * This class is responsible for deleting old messages from memory, so we don't * use too much of it. This is particularly important when processing 100s or * 1000s messages per second. */ public class MessageStoreGarbageCollector<T extends FormattedMessage> implements Runnable { /** Stores events for the UI to be updated. */ protected final EventQueueManager<T> uiEventQueue; private MessageListWithObservableTopicSummary<T> messages; private int minMessagesPerTopic; private boolean createTopicSummaryEvents; private boolean createBrowseEvents; private ManagedMessageStoreWithFiltering<T> store; private boolean running; public MessageStoreGarbageCollector(final ManagedMessageStoreWithFiltering<T> store, final MessageListWithObservableTopicSummary<T> messages, final EventQueueManager<T> uiEventQueue, final int minMessages, final boolean createTopicSummaryEvents, final boolean createBrowseEvents) { this.messages = messages; this.uiEventQueue = uiEventQueue; this.minMessagesPerTopic = minMessages; this.createTopicSummaryEvents = createTopicSummaryEvents; this.createBrowseEvents = createBrowseEvents; this.store = store; } public void setRunning(final boolean running) { this.running = running; } private void checkAndRemove(boolean shouldRemove) { // logger.trace("[{}] Checking if can delete messages...", messages.getName()); for (int i = messages.getMessages().size() - 1; i >=0; i--) { final T element = messages.getMessages().get(i); final int count = messages.getTopicSummary().getCountForTopic(element.getTopic()); if (count > minMessagesPerTopic) { // Remove from the store messages.remove(i); shouldRemove = messages.exceedingPreferredSize(); // Update topic summary and UI // Remove events are for the normal store if (createTopicSummaryEvents) { uiEventQueue.add(store, new TopicSummaryRemovedMessageEvent<T>(messages, element)); } // Index update are for the filtered store if (createBrowseEvents) { uiEventQueue.add(store, new BrowseRemovedMessageEvent<T>(messages, element, i + 1)); } if (!shouldRemove) { break; } } } } @Override public void run() { running = true; ThreadingUtils.logThreadStarting("Message Store Garbage Collector for " + messages.getName()); while (running) { if (ThreadingUtils.sleep(1000)) { break; } synchronized (messages.getMessages()) { boolean shouldRemove = messages.exceedingPreferredSize(); if (!shouldRemove) { continue; } checkAndRemove(shouldRemove); } } ThreadingUtils.logThreadEnding(); } }