public void run() { long end_time, wait_time; List<Request> requests = new LinkedList<Request>(); while (Thread.currentThread().equals(thread) && !suspended) { try { boolean keepGoing = false; end_time = System.currentTimeMillis() + max_bundling_time; do { Request firstRequest = (Request) queue.remove(INTERVAL); // throws a TimeoutException if it runs into timeout requests.add(firstRequest); if (!view_bundling) break; if (queue.size() > 0) { Request nextReq = (Request) queue.peek(); keepGoing = view_bundling && firstRequest.canBeProcessedTogether(nextReq); } else { wait_time = end_time - System.currentTimeMillis(); if (wait_time > 0) queue.waitUntilClosed( wait_time); // misnomer: waits until element has been added or q closed keepGoing = queue.size() > 0 && firstRequest.canBeProcessedTogether((Request) queue.peek()); } } while (keepGoing && System.currentTimeMillis() < end_time); try { process(requests); } finally { requests.clear(); } } catch (QueueClosedException e) { break; } catch (TimeoutException e) { break; } catch (Throwable catchall) { Util.sleep(50); } } }
/** * Assembles all the fragments into one buffer. Takes all Messages, and combines their buffers * into one buffer. This method does not check if the fragmentation is complete (use {@link * #isComplete()} to verify before calling this method) * * @return the complete message in one buffer */ private Message assembleMessage() { Message retval; byte[] combined_buffer, tmp; int combined_length = 0, length, offset; int index = 0; for (Message fragment : fragments) combined_length += fragment.getLength(); combined_buffer = new byte[combined_length]; retval = fragments[0].copy(false); // doesn't copy the payload, but copies the headers for (int i = 0; i < fragments.length; i++) { Message fragment = fragments[i]; fragments[i] = null; // help garbage collection a bit tmp = fragment.getRawBuffer(); length = fragment.getLength(); offset = fragment.getOffset(); System.arraycopy(tmp, offset, combined_buffer, index, length); index += length; } retval.setBuffer(combined_buffer); return retval; }
/** * Sets the new view and sends a VIEW_CHANGE event up and down the stack. If the view is a * MergeView (subclass of View), then digest will be non-null and has to be set before installing * the view. */ public void installView(View new_view, Digest digest) { ViewId vid = new_view.getVid(); List<Address> mbrs = new_view.getMembers(); ltime = Math.max( vid.getId(), ltime); // compute the logical time, regardless of whether the view is accepted // Discards view with id lower than or equal to our own. Will be installed without check if it // is the first view if (view != null) { ViewId view_id = view.getViewId(); int rc = vid.compareToIDs(view_id); if (rc <= 0) { if (log.isWarnEnabled() && rc < 0 && log_view_warnings) { // only scream if view is smaller, silently discard same views log.warn( local_addr + ": received view < current view;" + " discarding it (current vid: " + view_id + ", new vid: " + vid + ')'); } return; } } /* Check for self-inclusion: if I'm not part of the new membership, I just discard it. This ensures that messages sent in view V1 are only received by members of V1 */ if (!mbrs.contains(local_addr)) { if (log.isWarnEnabled() && log_view_warnings) log.warn(local_addr + ": not member of view " + new_view.getViewId() + "; discarding it"); return; } if (digest != null) { if (new_view instanceof MergeView) mergeDigest(digest); else setDigest(digest); } if (log.isDebugEnabled()) log.debug(local_addr + ": installing view " + new_view); Event view_event; synchronized (members) { view = new View(new_view.getVid(), new_view.getMembers()); view_event = new Event(Event.VIEW_CHANGE, new_view); // Set the membership. Take into account joining members if (!mbrs.isEmpty()) { members.set(mbrs); tmp_members.set(members); joining.removeAll(mbrs); // remove all members in mbrs from joining // remove all elements from 'leaving' that are not in 'mbrs' leaving.retainAll(mbrs); tmp_members.add(joining); // add members that haven't yet shown up in the membership tmp_members.remove( leaving); // remove members that haven't yet been removed from the membership // add to prev_members for (Address addr : mbrs) { if (!prev_members.contains(addr)) prev_members.add(addr); } } Address coord = determineCoordinator(); if (coord != null && coord.equals(local_addr) && !haveCoordinatorRole()) { becomeCoordinator(); } else { if (haveCoordinatorRole() && !local_addr.equals(coord)) { becomeParticipant(); merge_ack_collector.reset(null); // we don't need this one anymore } } } // - Changed order of passing view up and down (http://jira.jboss.com/jira/browse/JGRP-347) // - Changed it back (bela Sept 4 2007): http://jira.jboss.com/jira/browse/JGRP-564 // - Moved sending up view_event out of the synchronized block (bela Nov 2011) down_prot.down(view_event); // needed e.g. by failure detector or UDP up_prot.up(view_event); List<Address> tmp_mbrs = new_view.getMembers(); ack_collector.retainAll(tmp_mbrs); merge_ack_collector.retainAll(tmp_mbrs); if (new_view instanceof MergeView) merger.forceCancelMerge(); if (stats) { num_views++; prev_views.add(new Tuple<View, Long>(new_view, System.currentTimeMillis())); } }