/** * Add urgent messages, then non-urgent messages. Add a load message if need to. * * @param size * @param minSize * @param maxSize * @param now * @param messages * @return */ int addPriorityMessages( int size, int minSize, int maxSize, long now, ArrayList<MessageItem> messages, MutableBoolean incomplete) { synchronized (PeerMessageQueue.this) { // Urgent messages first. if (logMINOR) { int nonEmpty = nonEmptyItemsWithID == null ? 0 : nonEmptyItemsWithID.size(); int empty = emptyItemsWithID == null ? 0 : emptyItemsWithID.size(); int byID = itemsByID == null ? 0 : itemsByID.size(); if (nonEmpty + empty < byID) { Logger.error( this, "Leaking itemsByID? non empty = " + nonEmpty + " empty = " + empty + " by ID = " + byID + " on " + this); } else if (logDEBUG) Logger.debug( this, "Items: non empty " + nonEmpty + " empty " + empty + " by ID " + byID + " on " + this); } moveToUrgent(now); clearOldNonUrgent(now); size = addUrgentMessages(size, minSize, maxSize, now, messages); if (size < 0) { size = -size; incomplete.value = true; return size; } // If no more urgent messages, try to add some non-urgent messages too. size = addNonUrgentMessages(size, minSize, maxSize, now, messages); if (size < 0) { size = -size; incomplete.value = true; } return size; } }
/** * 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; } } }