Changeset 0a41052


Ignore:
Timestamp:
Sep 14, 2014 2:32:23 PM (6 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
67fb4e7
Parents:
a7763a0
Message:

SSU InboundMessageState? -
Rewrite PartialBitfield? for efficiency, less space and object churn
SSU ACKBitfield: Add ackCount()
PeerState?.fetchPartialACKs() improvements

Location:
router/java/src/net/i2p/router/transport/udp
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/net/i2p/router/transport/udp/ACKBitfield.java

    ra7763a0 r0a41052  
    66 */
    77interface ACKBitfield {
     8
    89    /** what message is this partially ACKing? */
    910    public long getMessageId();
     11
    1012    /** how many fragments are covered in this bitfield? */
    1113    public int fragmentCount();
     14
    1215    /** has the given fragment been received? */
    1316    public boolean received(int fragmentNum);
     17
    1418    /** has the entire message been received completely? */
    1519    public boolean receivedComplete();
     20
     21    /**
     22     *  Number of fragments acked in this bitfield.
     23     *  Faster than looping through received()
     24     *  @since 0.9.16
     25     */
     26    public int ackCount();
    1627}
  • router/java/src/net/i2p/router/transport/udp/InboundMessageState.java

    ra7763a0 r0a41052  
    221221
    222222    public ACKBitfield createACKBitfield() {
    223         return new PartialBitfield(_messageId, _fragments);
    224     }
    225    
    226     /**
    227      *  A true partial bitfield that is not complete.
     223        int sz = (_lastFragment >= 0) ? _lastFragment + 1 : _fragments.length;
     224        return new PartialBitfield(_messageId, _fragments, sz);
     225    }
     226   
     227    /**
     228     *  A true partial bitfield that is probably not complete.
     229     *  fragmentCount() will return 64 if unknown.
    228230     */
    229231    private static final class PartialBitfield implements ACKBitfield {
    230232        private final long _bitfieldMessageId;
    231         private final boolean _fragmentsReceived[];
     233        private final int _fragmentCount;
     234        private final int _ackCount;
     235        // bitfield, 1 for acked
     236        private final long _fragmentAcks;
    232237       
    233238        /**
    234239         *  @param data each element is non-null or null for received or not
     240         *  @param lastFragment size of data to use
    235241         */
    236         public PartialBitfield(long messageId, Object data[]) {
     242        public PartialBitfield(long messageId, Object data[], int size) {
     243            if (size > MAX_FRAGMENTS)
     244                throw new IllegalArgumentException();
    237245            _bitfieldMessageId = messageId;
    238             boolean fragmentsRcvd[] = null;
    239             for (int i = data.length - 1; i >= 0; i--) {
     246            int ackCount = 0;
     247            long acks = 0;
     248            for (int i = 0; i < size; i++) {
    240249                if (data[i] != null) {
    241                     if (fragmentsRcvd == null)
    242                         fragmentsRcvd = new boolean[i+1];
    243                     fragmentsRcvd[i] = true;
     250                    acks |= mask(i);
     251                    ackCount++;
    244252                }
    245253            }
    246             if (fragmentsRcvd == null)
    247                 _fragmentsReceived = new boolean[0];
    248             else
    249                 _fragmentsReceived = fragmentsRcvd;
    250         }
    251 
    252         public int fragmentCount() { return _fragmentsReceived.length; }
     254            _fragmentAcks = acks;
     255            _fragmentCount = size;
     256            _ackCount = ackCount;
     257        }
     258
     259        /**
     260         *  @param fragment 0-63
     261         */
     262        private static long mask(int fragment) {
     263            return 1L << fragment;
     264        }
     265
     266        public int fragmentCount() { return _fragmentCount; }
     267
     268        public int ackCount() { return _ackCount; }
    253269
    254270        public long getMessageId() { return _bitfieldMessageId; }
    255271
    256272        public boolean received(int fragmentNum) {
    257             if ( (fragmentNum < 0) || (fragmentNum >= _fragmentsReceived.length) )
     273            if (fragmentNum < 0 || fragmentNum >= _fragmentCount)
    258274                return false;
    259             return _fragmentsReceived[fragmentNum];
    260         }
    261 
    262         /** @return false always */
    263         public boolean receivedComplete() { return false; }
     275            return (_fragmentAcks & mask(fragmentNum)) != 0;
     276        }
     277
     278        public boolean receivedComplete() { return _ackCount == _fragmentCount; }
    264279       
    265280        @Override
     
    269284            buf.append(_bitfieldMessageId);
    270285            buf.append(" with ACKs for: ");
    271             for (int i = 0; i < _fragmentsReceived.length; i++)
    272                 if (_fragmentsReceived[i])
     286            for (int i = 0; i < _fragmentCount; i++) {
     287                if (received(i))
    273288                    buf.append(i).append(" ");
     289            }
     290            buf.append(" / ").append(_fragmentCount);
    274291            return buf.toString();
    275292        }
  • router/java/src/net/i2p/router/transport/udp/PeerState.java

    ra7763a0 r0a41052  
    10361036     */
    10371037    void fetchPartialACKs(List<ACKBitfield> rv) {
    1038         InboundMessageState states[] = null;
     1038        List<InboundMessageState> states = null;
    10391039        int curState = 0;
    10401040        synchronized (_inboundMessages) {
     
    10531053                    if (!state.isComplete()) {
    10541054                        if (states == null)
    1055                             states = new InboundMessageState[numMessages];
    1056                         states[curState++] = state;
     1055                            states = new ArrayList<InboundMessageState>(numMessages);
     1056                        states.add(state);
    10571057                    }
    10581058                }
     
    10601060        }
    10611061        if (states != null) {
    1062             // _inboundMessages is a Map (unordered), so why bother going backwards?
    1063             for (int i = curState-1; i >= 0; i--) {
    1064                 if (states[i] != null)
    1065                     rv.add(states[i].createACKBitfield());
     1062            for (InboundMessageState ims : states) {
     1063                ACKBitfield abf = ims.createACKBitfield();
     1064                if (!abf.receivedComplete())
     1065                    rv.add(abf);
    10661066            }
    10671067        }
     
    10771077
    10781078        public int fragmentCount() { return 0; }
     1079        public int ackCount() { return 0; }
    10791080        public long getMessageId() { return _msgId; }
    10801081        public boolean received(int fragmentNum) { return true; }
     
    18961897            int numSends = state.getMaxSends();
    18971898                       
    1898             int bits = bitfield.fragmentCount();
    1899             int numACKed = 0;
    1900             for (int i = 0; i < bits; i++)
    1901                 if (bitfield.received(i))
    1902                     numACKed++;
    1903            
     1899            int numACKed = bitfield.ackCount();
    19041900            _context.statManager().addRateData("udp.partialACKReceived", numACKed);
    19051901           
  • router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java

    ra7763a0 r0a41052  
    530530        public boolean receivedComplete() { return false; }
    531531
     532        /**
     533         *  Number of fragments acked in this bitfield.
     534         *  Faster than looping through received()
     535         *  @since 0.9.16
     536         */
     537        public int ackCount() {
     538            int rv = 0;
     539            for (int i = _bitfieldStart; i < _bitfieldStart + _bitfieldSize; i++) {
     540                byte b = _message[i];
     541                if ((b & 0x7f) != 0) {
     542                    for (int j = 0; j < 7; j++) {
     543                        if ((b & 0x01) != 0)
     544                            rv++;
     545                        b >>= 1;
     546                    }
     547                }
     548            }
     549            return rv;
     550        }
     551
    532552        public boolean received(int fragmentNum) {
    533553            if ( (fragmentNum < 0) || (fragmentNum >= _bitfieldSize*7) )
Note: See TracChangeset for help on using the changeset viewer.