* Matthew Toseland <toad at amphibian.dyndns.org> [2006-07-11 00:52:11]:

> Ummm...
> 
> Please don't take the lock on run() !!!! This is a long method which
> does lots of blocking I/O ! I wouldn't be surprised if this patch causes
> deadlocks... Also iirc finish() can do I/O, so again it shouldn't be
> locked. htl will not be decremented by any other thread than the one
> running run(), nor will req be changed by any other thread. However we
> may need some synchronization so that updates are noticed by other
> threads - but do not synchronize for long periods while e.g. doing I/O.

Ok, should be addressed in r9563

> 
> On Sun, Jul 09, 2006 at 10:12:01PM +0000, nextgens at freenetproject.org 
> wrote:
> > Author: nextgens
> > Date: 2006-07-09 22:11:57 +0000 (Sun, 09 Jul 2006)
> > New Revision: 9529
> > 
> > Modified:
> >    trunk/freenet/src/freenet/node/CHKInsertSender.java
> > Log:
> > Fixes a bug in CHKInsertSender and possibly locking issues
> > 
> > Modified: trunk/freenet/src/freenet/node/CHKInsertSender.java
> > ===================================================================
> > --- trunk/freenet/src/freenet/node/CHKInsertSender.java     2006-07-09 
> > 21:51:04 UTC (rev 9528)
> > +++ trunk/freenet/src/freenet/node/CHKInsertSender.java     2006-07-09 
> > 22:11:57 UTC (rev 9529)
> > @@ -52,17 +52,17 @@
> >             /** Have we received notice of the downstream success
> >              * or failure of dependant transfers from that node?
> >              * Includes timing out. */
> > -           boolean receivedCompletionNotice = false;
> > +           boolean receivedCompletionNotice;
> >             /** Timed out - didn't receive completion notice in
> >              * the allotted time?? */
> > -           boolean completionTimedOut = false;
> > +           boolean completionTimedOut;
> >             /** Was the notification of successful transfer? */
> >             boolean completionSucceeded;
> >             
> >             /** Have we completed the immediate transfer? */
> > -           boolean completedTransfer = false;
> > +           boolean completedTransfer;
> >             /** Did it succeed? */
> > -           boolean transferSucceeded = false;
> > +           boolean transferSucceeded;
> >             
> >             AwaitingCompletion(PeerNode pn, PartiallyReceivedBlock prb) {
> >                     this.pn = pn;
> > @@ -151,7 +151,7 @@
> >      final byte[] headers; // received BEFORE creation => we handle 
> > Accepted elsewhere
> >      final PartiallyReceivedBlock prb;
> >      final boolean fromStore;
> > -    private boolean receiveFailed = false;
> > +    private boolean receiveFailed;
> >      final double closestLocation;
> >      final long startTime;
> >      private boolean sentRequest;
> > @@ -161,13 +161,13 @@
> >      private Vector nodesWaitingForCompletion;
> >      
> >      /** Have all transfers completed and all nodes reported completion 
> > status? */
> > -    private boolean allTransfersCompleted = false;
> > +    private boolean allTransfersCompleted;
> >      
> >      /** Has a transfer timed out, either directly or downstream? */
> > -    private boolean transferTimedOut = false;
> > +    private boolean transferTimedOut;
> >      
> >      /** Runnable which waits for completion of all transfers */
> > -    private CompletionWaiter cw = null;
> > +    private CompletionWaiter cw;
> >  
> >      /** Time at which we set status to a value other than NOT_FINISHED */
> >      private long setStatusTime = -1;
> > @@ -193,7 +193,7 @@
> >          return super.toString()+" for "+uid;
> >      }
> >      
> > -    public void run() {
> > +    public synchronized void run() {
> >          short origHTL = htl;
> >          node.addInsertSender(myKey, htl, this);
> >          try {
> > @@ -215,12 +215,13 @@
> >          while(true) {
> >              if(receiveFailed) return; // don't need to set status as 
> > killed by InsertHandler
> >              
> > -            if(htl == 0) {
> > -                // Send an InsertReply back
> > -                finish(SUCCESS, null);
> > -                return;
> > +            synchronized (this) {
> > +                   if(htl == 0) {
> > +                           // Send an InsertReply back
> > +                           finish(SUCCESS, null);
> > +                           return;
> > +                   }
> >              }
> > -            
> >              // Route it
> >              PeerNode next;
> >              // Can backtrack, so only route to nodes closer than we are to 
> > target.
> > @@ -239,13 +240,15 @@
> >              Logger.minor(this, "Routing insert to "+next);
> >              nodesRoutedTo.add(next);
> >              
> > -            if(PeerManager.distance(target, nextValue) > 
> > PeerManager.distance(target, closestLocation)) {
> > -                Logger.minor(this, "Backtracking: target="+target+" 
> > next="+nextValue+" closest="+closestLocation);
> > -                htl = node.decrementHTL(source, htl);
> > +            Message req;
> > +            synchronized (this) {
> > +                   if(PeerManager.distance(target, nextValue) > 
> > PeerManager.distance(target, closestLocation)) {
> > +                           Logger.minor(this, "Backtracking: 
> > target="+target+" next="+nextValue+" closest="+closestLocation);
> > +                           htl = node.decrementHTL(source, htl);
> > +                   }
> > +
> > +                   req = DMT.createFNPInsertRequest(uid, htl, myKey, 
> > closestLocation);
> >              }
> > -            
> > -            Message req = DMT.createFNPInsertRequest(uid, htl, myKey, 
> > closestLocation);
> > -            
> >              // Wait for ack or reject... will come before even a locally 
> > generated DataReply
> >              
> >              MessageFilter mfAccepted = 
> > MessageFilter.create().setSource(next).setField(DMT.UID, 
> > uid).setTimeout(ACCEPTED_TIMEOUT).setType(DMT.FNPAccepted);
> > @@ -266,7 +269,9 @@
> >                             Logger.minor(this, "Not connected to "+next);
> >                             continue;
> >                     }
> > -            sentRequest = true;
> > +                   synchronized (this) {
> > +                           sentRequest = true;                             
> > +                   }
> >              
> >              if(receiveFailed) return; // don't need to set status as 
> > killed by InsertHandler
> >              Message msg = null;
> > @@ -277,7 +282,7 @@
> >               * followed by an Accepted. So we must loop here.
> >               */
> >              
> > -            while (true) {
> > +            while (msg==null || (msg.getSpec() != DMT.FNPAccepted)) {
> >                     
> >                             try {
> >                                     msg = node.usm.waitFor(mf, this);
> > @@ -326,7 +331,6 @@
> >                                     break;
> >                             }
> >                             // Otherwise is an FNPAccepted
> > -                           break;
> >                     }
> >              
> >              if(msg == null || msg.getSpec() != DMT.FNPAccepted) continue;
> > @@ -421,8 +425,10 @@
> >                             if (msg.getSpec() == DMT.FNPRouteNotFound) {
> >                                     Logger.minor(this, "Rejected: RNF");
> >                                     short newHtl = msg.getShort(DMT.HTL);
> > -                                   if (htl > newHtl)
> > -                                           htl = newHtl;
> > +                                   synchronized (this) {
> > +                                           if (htl > newHtl)
> > +                                                   htl = newHtl;           
> >                                 
> > +                                   }
> >                                     // Finished as far as this node is 
> > concerned
> >                                     next.successNotOverload();
> >                                     break;
> > @@ -486,17 +492,18 @@
> >                             if (msg.getSpec() != DMT.FNPInsertReply) {
> >                                     Logger.error(this, "Unknown reply: " + 
> > msg);
> >                                     finish(INTERNAL_ERROR, next);
> > +                                   return;
> > +                           }else{
> > +                                   // Our task is complete
> > +                                   next.successNotOverload();
> > +                                   finish(SUCCESS, next);
> > +                                   return;
> >                             }
> > -                           
> > -                           // Our task is complete
> > -                           next.successNotOverload();
> > -                           finish(SUCCESS, next);
> > -                           return;
> >                     }
> >             }
> >     }
> >  
> > -   private boolean hasForwardedRejectedOverload = false;
> > +   private boolean hasForwardedRejectedOverload;
> >      
> >      synchronized boolean receivedRejectedOverload() {
> >             return hasForwardedRejectedOverload;
> > @@ -513,11 +520,11 @@
> >      
> >      private void finish(int code, PeerNode next) {
> >          Logger.minor(this, "Finished: "+code+" on "+this, new 
> > Exception("debug"));
> > -        if(status != NOT_FINISHED)
> > -           throw new IllegalStateException("finish() called with "+code+" 
> > when was already "+status);
> > -
> > +       
> >          synchronized(this) {
> > -        
> > +            if(status != NOT_FINISHED)
> > +                   throw new IllegalStateException("finish() called with 
> > "+code+" when was already "+status);
> > +           
> >             setStatusTime = System.currentTimeMillis();
> >             
> >             if(code == ROUTE_NOT_FOUND && !sentRequest)
> > @@ -559,11 +566,11 @@
> >          Logger.minor(this, "Returning from finish()");
> >      }
> >  
> > -    public int getStatus() {
> > +    public synchronized int getStatus() {
> >          return status;
> >      }
> >      
> > -    public short getHTL() {
> > +    public synchronized short getHTL() {
> >          return htl;
> >      }
> >  
> > @@ -578,7 +585,7 @@
> >      /**
> >       * @return The current status as a string
> >       */
> > -    public String getStatusString() {
> > +    public synchronized String getStatusString() {
> >          if(status == SUCCESS)
> >              return "SUCCESS";
> >          if(status == ROUTE_NOT_FOUND)
> > @@ -596,18 +603,19 @@
> >          return "UNKNOWN STATUS CODE: "+status;
> >      }
> >  
> > -   public boolean sentRequest() {
> > +   public synchronized boolean sentRequest() {
> >             return sentRequest;
> >     }
> >     
> >     private void makeCompletionWaiter() {
> > +           Thread t;
> >             synchronized(this) {
> >                     if(cw == null)
> >                             cw = new CompletionWaiter();
> >                     else
> >                             return;
> > +                   t = new Thread(cw, "Completion waiter for "+uid);
> >             }
> > -           Thread t = new Thread(cw, "Completion waiter for "+uid);
> >             t.setDaemon(true);
> >             t.start();
> >     }
> > @@ -813,7 +821,7 @@
> >             }
> >     }
> >  
> > -   public boolean completed() {
> > +   public synchronized boolean completed() {
> >             return allTransfersCompleted;
> >     }
> -- 
> Matthew J Toseland - toad at amphibian.dyndns.org
> Freenet Project Official Codemonkey - http://freenetproject.org/
> ICTHUS - Nothing is impossible. Our Boss says so.



> _______________________________________________
> Devl mailing list
> Devl at freenetproject.org
> http://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl

Reply via email to