예제 #1
0
 // We probably just do not have this object locally.
 /// <exception cref="System.IO.IOException"></exception>
 private void MarkCommon(RevObject obj, PacketLineIn.AckNackResult anr)
 {
     if (statelessRPC && anr == PacketLineIn.AckNackResult.ACK_COMMON && !obj.Has(STATE
                                                                                  ))
     {
         StringBuilder s;
         s = new StringBuilder(6 + Constants.OBJECT_ID_STRING_LENGTH);
         s.Append("have ");
         //$NON-NLS-1$
         s.Append(obj.Name);
         s.Append('\n');
         pckState.WriteString(s.ToString());
         obj.Add(STATE);
     }
     obj.Add(COMMON);
     if (obj is RevCommit)
     {
         ((RevCommit)obj).Carry(COMMON);
     }
 }
예제 #2
0
        /// <exception cref="System.IO.IOException"></exception>
        /// <exception cref="NGit.Transport.BasePackFetchConnection.CancelledException"></exception>
        private void Negotiate(ProgressMonitor monitor)
        {
            MutableObjectId ackId                  = new MutableObjectId();
            int             resultsPending         = 0;
            int             havesSent              = 0;
            int             havesSinceLastContinue = 0;
            bool            receivedContinue       = false;
            bool            receivedAck            = false;
            bool            receivedReady          = false;

            if (statelessRPC)
            {
                state.WriteTo(@out, null);
            }
            NegotiateBegin();
            while (!receivedReady)
            {
                RevCommit c = walk.Next();
                if (c == null)
                {
                    goto SEND_HAVES_break;
                }
                pckOut.WriteString("have " + c.Id.Name + "\n");
                havesSent++;
                havesSinceLastContinue++;
                if ((31 & havesSent) != 0)
                {
                    // We group the have lines into blocks of 32, each marked
                    // with a flush (aka end). This one is within a block so
                    // continue with another have line.
                    //
                    continue;
                }
                if (monitor.IsCancelled())
                {
                    throw new BasePackFetchConnection.CancelledException();
                }
                pckOut.End();
                resultsPending++;
                // Each end will cause a result to come back.
                if (havesSent == 32 && !statelessRPC)
                {
                    // On the first block we race ahead and try to send
                    // more of the second block while waiting for the
                    // remote to respond to our first block request.
                    // This keeps us one block ahead of the peer.
                    //
                    continue;
                }
                for (; ;)
                {
                    PacketLineIn.AckNackResult anr = pckIn.ReadACK(ackId);
                    switch (anr)
                    {
                    case PacketLineIn.AckNackResult.NAK:
                    {
                        // More have lines are necessary to compute the
                        // pack on the remote side. Keep doing that.
                        //
                        resultsPending--;
                        goto READ_RESULT_break;
                    }

                    case PacketLineIn.AckNackResult.ACK:
                    {
                        // The remote side is happy and knows exactly what
                        // to send us. There is no further negotiation and
                        // we can break out immediately.
                        //
                        multiAck       = BasePackFetchConnection.MultiAck.OFF;
                        resultsPending = 0;
                        receivedAck    = true;
                        if (statelessRPC)
                        {
                            state.WriteTo(@out, null);
                        }
                        goto SEND_HAVES_break;
                    }

                    case PacketLineIn.AckNackResult.ACK_CONTINUE:
                    case PacketLineIn.AckNackResult.ACK_COMMON:
                    case PacketLineIn.AckNackResult.ACK_READY:
                    {
                        // The server knows this commit (ackId). We don't
                        // need to send any further along its ancestry, but
                        // we need to continue to talk about other parts of
                        // our local history.
                        //
                        MarkCommon(walk.ParseAny(ackId), anr);
                        receivedAck            = true;
                        receivedContinue       = true;
                        havesSinceLastContinue = 0;
                        if (anr == PacketLineIn.AckNackResult.ACK_READY)
                        {
                            receivedReady = true;
                        }
                        break;
                    }
                    }
                    if (monitor.IsCancelled())
                    {
                        throw new BasePackFetchConnection.CancelledException();
                    }
                    READ_RESULT_continue :;
                }
                READ_RESULT_break :;
                if (statelessRPC)
                {
                    state.WriteTo(@out, null);
                }
                if (receivedContinue && havesSinceLastContinue > MAX_HAVES)
                {
                    // Our history must be really different from the remote's.
                    // We just sent a whole slew of have lines, and it did not
                    // recognize any of them. Avoid sending our entire history
                    // to them by giving up early.
                    //
                    goto SEND_HAVES_break;
                }
                SEND_HAVES_continue :;
            }
            SEND_HAVES_break :;
            // Tell the remote side we have run out of things to talk about.
            //
            if (monitor.IsCancelled())
            {
                throw new BasePackFetchConnection.CancelledException();
            }
            if (!receivedReady || !noDone)
            {
                // When statelessRPC is true we should always leave SEND_HAVES
                // loop above while in the middle of a request. This allows us
                // to just write done immediately.
                //
                pckOut.WriteString("done\n");
                pckOut.Flush();
            }
            if (!receivedAck)
            {
                // Apparently if we have never received an ACK earlier
                // there is one more result expected from the done we
                // just sent to the remote.
                //
                multiAck = BasePackFetchConnection.MultiAck.OFF;
                resultsPending++;
            }
            while (resultsPending > 0 || multiAck != BasePackFetchConnection.MultiAck.OFF)
            {
                PacketLineIn.AckNackResult anr = pckIn.ReadACK(ackId);
                resultsPending--;
                switch (anr)
                {
                case PacketLineIn.AckNackResult.NAK:
                {
                    // A NAK is a response to an end we queued earlier
                    // we eat it and look for another ACK/NAK message.
                    //
                    break;
                }

                case PacketLineIn.AckNackResult.ACK:
                {
                    // A solitary ACK at this point means the remote won't
                    // speak anymore, but is going to send us a pack now.
                    //
                    goto READ_RESULT_break2;
                }

                case PacketLineIn.AckNackResult.ACK_CONTINUE:
                case PacketLineIn.AckNackResult.ACK_COMMON:
                case PacketLineIn.AckNackResult.ACK_READY:
                {
                    // We will expect a normal ACK to break out of the loop.
                    //
                    multiAck = BasePackFetchConnection.MultiAck.CONTINUE;
                    break;
                }
                }
                if (monitor.IsCancelled())
                {
                    throw new BasePackFetchConnection.CancelledException();
                }
                READ_RESULT_continue :;
            }
            READ_RESULT_break2 :;
        }
예제 #3
0
        private void Negotiate(ProgressMonitor monitor)
        {
            var  ackId                  = new MutableObjectId();
            int  resultsPending         = 0;
            int  havesSent              = 0;
            int  havesSinceLastContinue = 0;
            bool receivedContinue       = false;
            bool receivedAck            = false;
            bool sendHaves              = true;

            NegotiateBegin();
            while (sendHaves)
            {
                RevCommit c = _walk.next();
                if (c == null)
                {
                    break;
                }

                pckOut.WriteString("have " + c.getId().Name + "\n");
                havesSent++;
                havesSinceLastContinue++;

                if ((31 & havesSent) != 0)
                {
                    continue;
                }

                if (monitor.IsCancelled)
                {
                    throw new CancelledException();
                }

                pckOut.End();
                resultsPending++;

                if (havesSent == 32)
                {
                    continue;
                }

                for (; ;)
                {
                    PacketLineIn.AckNackResult anr = pckIn.readACK(ackId);

                    if (anr == PacketLineIn.AckNackResult.NAK)
                    {
                        resultsPending--;
                        break;
                    }

                    if (anr == PacketLineIn.AckNackResult.ACK)
                    {
                        _multiAck      = false;
                        resultsPending = 0;
                        receivedAck    = true;
                        sendHaves      = false;
                        break;
                    }

                    if (anr == PacketLineIn.AckNackResult.ACK_CONTINUE)
                    {
                        MarkCommon(_walk.parseAny(ackId));
                        receivedAck            = true;
                        receivedContinue       = true;
                        havesSinceLastContinue = 0;
                    }

                    if (monitor.IsCancelled)
                    {
                        throw new CancelledException();
                    }
                }

                if (receivedContinue && havesSinceLastContinue > MAX_HAVES)
                {
                    break;
                }
            }

            if (monitor.IsCancelled)
            {
                throw new CancelledException();
            }
            pckOut.WriteString("done\n");
            pckOut.Flush();

            if (!receivedAck)
            {
                _multiAck = false;
                resultsPending++;
            }

            while (resultsPending > 0 || _multiAck)
            {
                PacketLineIn.AckNackResult anr = pckIn.readACK(ackId);
                resultsPending--;

                if (anr == PacketLineIn.AckNackResult.ACK)
                {
                    break;
                }

                if (anr == PacketLineIn.AckNackResult.ACK_CONTINUE)
                {
                    _multiAck = true;
                }

                if (monitor.IsCancelled)
                {
                    throw new CancelledException();
                }
            }
        }