Feb 21st, Jiandan

There're two options:
1. add another link:nextCausal to each per-writer-log item to insert all item in a causal order defined by AcceptStamp.
     InvalIterator.getNext() will get a reference of the item.

     Bad: add a little bit more overhead to applyInval than the original one
               need more effort to change the current code.
     Good: the overhead only occurs at applyInval once, InvalIterator.getNext() will have only O(1) overhead

2. add a per-writer-log pointer in invalIterator
    bad: for each getNext might still incur O(#nodes) overhead to check all pointers
    good: can leave UpdateLog untouched -- simple.


So I pick 1 considering the overall gain we get.




Summary of Changes need:
=======================

(1) InvalListItem class:
    add a nextCausal link to per-writer-log InvalListItem s.t. 
    the nextCausal will always point to the next non-gap-filling causal item.

(2) InvalIterator class:
    move out the Accumulating Imprecise part to OutgoingConnection.
    just simply return the nextCausal invalidation.

(3) OutgoingConnectionEventMailbox:
    Coordinate the OutgoingConnectionWorker 
    between UpdateLog and OutgoingConnection. 

    Why?

    Issues with current design:
    
     OutgoingConnectionWorker is a single-thread for three tasks:
     1. deal with addSubscription/removeSubscription requests
     2. send catchup streams
     3. sending next new invalidation by calling UpdateLog.getNext()

    Currently, the possible blocking it has is:
     block at UpdateLog.getNext() due to no new updates which have a timeout
    
    During the blocking, the new coming addSub/removeSub requests can't be
    applied until it returns due to timeout if no new updates ever issued.


    Another issue with the worker is about Accumulating imprecise invalidation:
    currently, the accumulating is done in InvalIterator.
    Then it is possible that while InvalIterator is accumulating impreciseInv
    for a certain accumulatingTimeout period, there're new addSub/removeSub
    coming. Then what we will see is that the processing of addSub/removeSub 
    has a huge delay.


    Solution:
   
    add OutgoingConnectionEventMailbox to coordinate the worker and updateLog
    and outgoingConnection.

    OutgoingConnectionEventMailbox:
 
    1. block: 
       the worker only wait on OutgoingConnectionEventMailbox.getNextEvent() if 
       there's no pending requests or new updates.
 
    2. notify:
       OutgoingConnection will notify mailbox when there's new request
       UpdateLog will notify mailbox when there's new updates.

    move accumulating to Worker.

(4) IncomingConnection keeps a pointer of the last item just applied
    to reduce the overhead of applying one item. right now. it's O(N).





InvalIterator::
==============

InvalIterator is very simple: just return the next non-gap-filling Object.
leave accumulation of imprecise invalidation to OutgoingConnection
Redesign for the getNext timeout and impreciseInvalidation timeout.

assumption: InvalListItem item's invaliadtion member can change, but
the invariant is that item.start will always be the same.

add a new member besides CVV: 
  InvalListItem currPos;// the current invalidate just returned.
			//    initially null,
			// it will never be a gap-filling item    
			//at the end, it remain the last one in the log.


return null or next causal;
Object getNext(){
     	
   newPos=updateLog.getNext(newPos, cvv);
   if (newPos == null){
     return nul;
   } else{
      newInv = newPos.getInv(); //note: newPos.inv might change, 
      //but it's ok because, the cvv only advances with the inv that it returns.
      //The invariant that the start won't change can guarantee that the invalidate returns will
      //be the next causal.
      cvv.advance(newInv.getEndVV());
      return newInv;
   }
} 


UpdateLog
=========

UpdateLog::per-writer-log head


UpdateLog::merge

UpdateLog.getNext(newPos, cvv){
  while((newPos!null) && (newPos.getNextCausal()).inv included in cvv)){
     newPos=newPos.getNextCausal();
  }
  return newPos.
}


SingleWriterLogUncommited:
=========================
/**
   change 1. add a new parameter currentPointer so that 
             it can search starting from the currentPointer.

          2. return an InvalListItem instead of a GeneralInval
*/

Another option: completely expose InvalListItem,
then InvalIterator can just call InvalListItem.getNextByStart(long start).

InvalListItem getNextByStart(InvalListItem, start){
  

  void merge(){
      //need a lot of work to update the causalNextLink.
  }
}



OutgoingConnectionNextEventMailbox
==================================

queue, ii;

//called by OutgoingConnectionWorker
synchronized NextEvent getNext(){

  while (queue.isEmpty() && ii.hasNoNext()){
     wait();
  }
  if(!queue.isEmpty()){
    return queue.getNext();
  }
  if (ii.hasNewUpdate()){
    return ii.getNext();
  }

}


//called by OutgoingConnectionPool
synchronized void addNewRequest(newRequest){
   queue.add(newRequest);
   notifyAll();
}

//called by UpdateLog
//Note: don't put it under any lock.--> deadlock
synchronized void newUpdate(){
   notifyAll();
}



OutgoingConnection(){
  mailBox = new OutgoingConnectionMailbox();
  outgoingConnectionMailBoxTable.add(mailbox);
}


OutgoingConnectionMailboxTable
==============================
bound the size of Table.

   boolean add(mailbox); //fail if over sized.
   // that's ok, the OutgoingConnection can fall back to the 
   // old expensive getNext().
   void getNewUpdates();//for all mailbox() call newUpdate();




