Example #1
0
        /**
         * Note that a LinkProtocolState only gets a lock *AFTER* it has
         * received a LinkMessageReply.  Prior to that, the Linker that
         * created it holds the lock (if the _linker.Target is not null).
         *
         * So, given that we are being asked to transfer a lock, we must
         * have already gotten our LinkMessageReply set, or we wouldn't
         * hold the lock in the first place.
         *
         * So, we only transfer locks to other Linkers when we are finished
         * since us holding a lock means we have already head some
         * communication from the other side.
         *
         * Since the CT.Lock and CT.Unlock methods can't be called when this
         * is being called, we know that _target_lock won't change during
         * this method.
         */
        public bool AllowLockTransfer(Address a, string contype, ILinkLocker l)
        {
            bool hold_lock = (a.Equals(_target_lock) && contype == _contype);

            if (false == hold_lock)
            {
                //This is a bug.
                throw new Exception(String.Format("We don't hold the lock: {0}", a));
            }
            if ((l is Linker) && IsFinished)
            {
                return(true);
            }
            return(false);
        }
 public bool AllowLockTransfer(Address a, string contype, ILinkLocker new_locker) {
   return false;
 }
Example #3
0
 public bool AllowLockTransfer(Address a, string contype, ILinkLocker new_locker)
 {
     return(false);
 }
 /**
  * Note that a LinkProtocolState only gets a lock *AFTER* it has
  * received a LinkMessageReply.  Prior to that, the Linker that
  * created it holds the lock (if the _linker.Target is not null).
  *
  * So, given that we are being asked to transfer a lock, we must
  * have already gotten our LinkMessageReply set, or we wouldn't
  * hold the lock in the first place.
  *
  * So, we only transfer locks to other Linkers when we are finished
  * since us holding a lock means we have already head some
  * communication from the other side.
  * 
  * Since the CT.Lock and CT.Unlock methods can't be called when this
  * is being called, we know that _target_lock won't change during
  * this method.
  */
 public bool AllowLockTransfer(Address a, string contype, ILinkLocker l)
 {
   bool hold_lock = (a.Equals( _target_lock ) && contype == _contype);
   if( false == hold_lock ) {
     //This is a bug.
     throw new Exception(String.Format("We don't hold the lock: {0}", a));
   }
   if( (l is Linker) && IsFinished ) {
     return true;
   }
   return false;
 }
Example #5
0
    /**
     * Allow if we are transfering to a LinkProtocolState or ConnectionPacketHandler
     * Note this method does not change anything, if the transfer is done, it
     * is done by the ConnectionTable while it holds its lock.
     */
    public bool AllowLockTransfer(Address a, string contype, ILinkLocker l) {
      bool allow = false;
      bool hold_lock = (a.Equals( _target_lock ) && contype == _contype);
      if( false == hold_lock ) {
        //We don't even hold this lock!
        throw new Exception(
                            String.Format("{2} asked to transfer a lock({0}) we don't hold: ({1})",
                                          a, _target_lock, this));
      }
      if( l is Linker ) {
        //Never transfer to another linker:
      }
      else if ( l is ConnectionPacketHandler.CphState ) {
      /**
       * The ConnectionPacketHandler only locks when it
       * has actually received a packet.  This is a "bird in the
       * hand" situation, however, if both sides in the double
       * link case transfer the lock, then we have accomplished
       * nothing.
       *
       * There is a specific case to worry about: the case of
       * a firewall, where only one node can contact the other.
       * In this case, it may be very difficult to connect if
       * we don't eventually transfer the lock to the
       * ConnectionPacketHandler.  In the case of bi-directional
       * connectivity, we only transfer the lock if the
       * address we are locking is greater than our own (which
       * clearly cannot be true for both sides).
       * 
       * To handle the firewall case, we keep count of how
       * many times we have been asked to transfer the lock.  On
       * the third time we are asked, we assume we are in the firewall
       * case and we allow the transfer, this is just a hueristic.
       */
        int reqs = Interlocked.Increment(ref _cph_transfer_requests);
        if ( (reqs >= 3 ) || ( a.CompareTo( LocalNode.Address ) > 0) ) {
          allow = true;
        }
      }
      else if( l is LinkProtocolState ) {
        LinkProtocolState lps = (LinkProtocolState)l;
        /**
         * Or Transfer the lock to a LinkProtocolState if:
         * 1) We created this LinkProtocolState
         * 2) The LinkProtocolState has received a packet
         */
        if( (lps.Linker == this ) && ( lps.LinkMessageReply != null ) ) {
          allow = true;
        }
      }
#if LINK_DEBUG
      if (ProtocolLog.LinkDebug.Enabled) {
	  ProtocolLog.Write(ProtocolLog.LinkDebug,
                            String.Format("{0}: Linker({1}) {2}: transfering lock on {3} to {4}",
                              _local_n.Address, _lid, (_target_lock == null), a, l));
      }
#endif
      return allow;
    }
Example #6
0
        /**
         * Allow if we are transfering to a LinkProtocolState or ConnectionPacketHandler
         * Note this method does not change anything, if the transfer is done, it
         * is done by the ConnectionTable while it holds its lock.
         */
        public bool AllowLockTransfer(Address a, string contype, ILinkLocker l)
        {
            bool allow     = false;
            bool hold_lock = (a.Equals(_target_lock) && contype == _contype);

            if (false == hold_lock)
            {
                //We don't even hold this lock!
                throw new Exception(
                          String.Format("{2} asked to transfer a lock({0}) we don't hold: ({1})",
                                        a, _target_lock, this));
            }
            if (l is Linker)
            {
                //Never transfer to another linker:
            }
            else if (l is ConnectionPacketHandler.CphState)
            {
                /**
                 * The ConnectionPacketHandler only locks when it
                 * has actually received a packet.  This is a "bird in the
                 * hand" situation, however, if both sides in the double
                 * link case transfer the lock, then we have accomplished
                 * nothing.
                 *
                 * There is a specific case to worry about: the case of
                 * a firewall, where only one node can contact the other.
                 * In this case, it may be very difficult to connect if
                 * we don't eventually transfer the lock to the
                 * ConnectionPacketHandler.  In the case of bi-directional
                 * connectivity, we only transfer the lock if the
                 * address we are locking is greater than our own (which
                 * clearly cannot be true for both sides).
                 *
                 * To handle the firewall case, we keep count of how
                 * many times we have been asked to transfer the lock.  On
                 * the third time we are asked, we assume we are in the firewall
                 * case and we allow the transfer, this is just a hueristic.
                 */
                int reqs = Interlocked.Increment(ref _cph_transfer_requests);
                if ((reqs >= 3) || (a.CompareTo(LocalNode.Address) > 0))
                {
                    allow = true;
                }
            }
            else if (l is LinkProtocolState)
            {
                LinkProtocolState lps = (LinkProtocolState)l;

                /**
                 * Or Transfer the lock to a LinkProtocolState if:
                 * 1) We created this LinkProtocolState
                 * 2) The LinkProtocolState has received a packet
                 */
                if ((lps.Linker == this) && (lps.LinkMessageReply != null))
                {
                    allow = true;
                }
            }
#if LINK_DEBUG
            if (BU.ProtocolLog.LinkDebug.Enabled)
            {
                BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug,
                                     String.Format("{0}: Linker({1}) {2}: transfering lock on {3} to {4}",
                                                   _local_n.Address, _lid, (_target_lock == null), a, l));
            }
#endif
            return(allow);
        }