/** * Add messages to <code>messages</code> until there are no more messages to add or <code>size * </code> would exceed <code>maxSize</code>. If <code>size == maxSize</code>, a message in the * queue will be added even if it makes <code>size</code> exceed <code>maxSize</code>. If <code> * isUrgent</code> is set, only messages that are considered urgent are added. * * @param size the current size of <code>messages</code> * @param minSize the size when <code>messages</code> is empty * @param maxSize the maximum size of <code>messages</code> * @param now the current time * @param messages the list that messages will be added to * @param isUrgent <code>true</code> if only urgent messages should be added * @return the size of <code>messages</code>, multiplied by -1 if there were messages that * didn't fit */ private int addUrgentMessages( int size, int minSize, int maxSize, long now, ArrayList<MessageItem> messages) { assert (size >= 0); assert (minSize >= 0); assert (maxSize >= minSize); if (size < 0) size = -size; // FIXME remove extra paranoia int added = 0; while (true) { boolean addedNone = true; int lists = 0; if (nonEmptyItemsWithID == null) return size; lists += nonEmptyItemsWithID.size(); Items list = nonEmptyItemsWithID.head(); for (int i = 0; i < lists && list != null; i++) { if (list.items.isEmpty()) { // Should not happen, but check for it anyway since it keeps happening. :( Logger.error(this, "List is in nonEmptyItemsWithID yet it is empty?!: " + list); nonEmptyItemsWithID.remove(list); addToEmptyBackward(list); if (nonEmptyItemsWithID.isEmpty()) return size; list = nonEmptyItemsWithID.head(); continue; } MessageItem item = list.items.getFirst(); int thisSize = item.getLength(); boolean oversize = false; if (size + 2 + thisSize > maxSize) { if (size == minSize) { // Won't fit regardless, send it on its own. oversize = true; } else { // Send what we have so far. if (logDEBUG && added != 0) Logger.debug( this, "Added " + added + " urgent messages, could add more but out of space at " + size); return -size; } } size += 2 + thisSize; list.items.removeFirst(); // Move to end of list. Items prev = list.getPrev(); nonEmptyItemsWithID.remove(list); list.timeLastSent = now; if (!list.items.isEmpty()) { addToNonEmptyBackward(list); } else { addToEmptyBackward(list); } if (prev == null) list = nonEmptyItemsWithID.head(); else list = prev.getNext(); messages.add(item); added++; addedNone = false; if (oversize) { if (logDEBUG) Logger.debug(this, "Returning with oversize urgent message"); return size; } } if (addedNone) { if (logDEBUG && added != 0) Logger.debug( this, "Added " + added + " urgent messages, size now " + size + " no more queued at this priority"); return size; } } }
private int addNonUrgentMessages( int size, int minSize, int maxSize, long now, ArrayList<MessageItem> messages) { assert (size >= 0); assert (minSize >= 0); assert (maxSize >= minSize); if (size < 0) size = -size; // FIXME remove extra paranoia if (itemsNonUrgent == null) return size; int added = 0; for (ListIterator<MessageItem> items = itemsNonUrgent.listIterator(); items.hasNext(); ) { MessageItem item = items.next(); int thisSize = item.getLength(); boolean oversize = false; if (size + 2 + thisSize > maxSize) { if (size == minSize) { // Won't fit regardless, send it on its own. oversize = true; } else { // Send what we have so far. if (logDEBUG && added != 0) Logger.debug( this, "Returning with " + added + " non-urgent messages (have more but they don't fit)"); return -size; } } size += 2 + thisSize; items.remove(); messages.add(item); if (itemsByID != null) { long id = item.getID(); Items tracker = itemsByID.get(id); if (tracker != null) { tracker.timeLastSent = now; DoublyLinkedList<? super Items> parent = tracker.getParent(); // Demote the corresponding tracker to maintain round-robin. if (tracker.items.isEmpty()) { if (emptyItemsWithID == null) emptyItemsWithID = new DoublyLinkedListImpl<Items>(); if (parent == null) { Logger.error(this, "Tracker is in itemsByID but not in either list! (empty)"); } else if (parent == emptyItemsWithID) { // Normal. Remove it so we can re-add it in the right place. emptyItemsWithID.remove(tracker); } else if (parent == nonEmptyItemsWithID) { Logger.error(this, "Tracker is in non empty items list when is empty"); nonEmptyItemsWithID.remove(tracker); } else assert (false); addToEmptyBackward(tracker); } else { if (nonEmptyItemsWithID == null) nonEmptyItemsWithID = new DoublyLinkedListImpl<Items>(); if (parent == null) { Logger.error(this, "Tracker is in itemsByID but not in either list! (non-empty)"); } else if (parent == nonEmptyItemsWithID) { // Normal. Remove it so we can re-add it in the right place. nonEmptyItemsWithID.remove(tracker); } else if (parent == emptyItemsWithID) { Logger.error(this, "Tracker is in empty items list when is non-empty"); emptyItemsWithID.remove(tracker); } else assert (false); addToNonEmptyBackward(tracker); } } } added++; if (oversize) { if (logDEBUG) Logger.debug(this, "Returning with non-urgent oversize message"); return size; } } if (logDEBUG && added != 0) Logger.debug(this, "Returning with " + added + " non-urgent messages (all gone)"); return size; }