Ejemplo n.º 1
0
void
tr_bandwidthSetParent( tr_bandwidth  * b,
                       tr_bandwidth  * parent )
{
    assert( tr_isBandwidth( b ) );
    assert( b != parent );

    if( b->parent )
    {
        void * removed;

        assert( tr_isBandwidth( b->parent ) );

        removed = tr_ptrArrayRemoveSorted( &b->parent->children, b, comparePointers );
        assert( removed == b );
        assert( tr_ptrArrayFindSorted( &b->parent->children, b, comparePointers ) == NULL );

        b->parent = NULL;
    }

    if( parent )
    {
        assert( tr_isBandwidth( parent ) );
        assert( parent->parent != b );

        tr_ptrArrayInsertSorted( &parent->children, b, comparePointers );
        assert( tr_ptrArrayFindSorted( &parent->children, b, comparePointers ) == b );
        b->parent = parent;
    }
}
Ejemplo n.º 2
0
static void
allocateBandwidth (tr_bandwidth  * b,
                   tr_priority_t   parent_priority,
                   tr_direction    dir,
                   unsigned int    period_msec,
                   tr_ptrArray   * peer_pool)
{
    const tr_priority_t priority = MAX (parent_priority, b->priority);

    assert (tr_isBandwidth (b));
    assert (tr_isDirection (dir));

    /* set the available bandwidth */
    if (b->band[dir].isLimited)
    {
        const uint64_t nextPulseSpeed = b->band[dir].desiredSpeed_Bps;
        b->band[dir].bytesLeft = (unsigned int)(nextPulseSpeed * period_msec) / 1000u;
    }

    /* add this bandwidth's peer, if any, to the peer pool */
    if (b->peer != NULL) {
        b->peer->priority = priority;
        tr_ptrArrayAppend (peer_pool, b->peer);
    }

    /* traverse & repeat for the subtree */
    if (1) {
        int i;
        struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayBase (&b->children);
        const int n = tr_ptrArraySize (&b->children);
        for (i=0; i<n; ++i)
            allocateBandwidth (children[i], priority, dir, period_msec, peer_pool);
    }
}
Ejemplo n.º 3
0
void
tr_bandwidthUsed( tr_bandwidth  * b,
                  tr_direction    dir,
                  size_t          byteCount,
                  tr_bool         isPieceData,
                  uint64_t        now )
{
    struct tr_band * band;

    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    band = &b->band[dir];

    if( band->isLimited && isPieceData )
        band->bytesLeft -= MIN( band->bytesLeft, byteCount );

#ifdef DEBUG_DIRECTION
if( ( dir == DEBUG_DIRECTION ) && ( band->isLimited ) )
fprintf( stderr, "%p consumed %5zu bytes of %5s data... was %6zu, now %6zu left\n",
         b, byteCount, (isPieceData?"piece":"raw"), oldBytesLeft, band->bytesLeft );
#endif

    bytesUsed( now, &band->raw, byteCount );

    if( isPieceData )
        bytesUsed( now, &band->piece, byteCount );

    if( b->parent != NULL )
        tr_bandwidthUsed( b->parent, dir, byteCount, isPieceData, now );
}
Ejemplo n.º 4
0
double
tr_bandwidthGetPieceSpeed( const tr_bandwidth * b, tr_direction dir )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    return getSpeed( &b->band[dir].piece, HISTORY_MSEC );
}
Ejemplo n.º 5
0
unsigned int
tr_bandwidthGetPieceSpeed_Bps( const tr_bandwidth * b, const uint64_t now, const tr_direction dir )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    return getSpeed_Bps( &b->band[dir].piece, HISTORY_MSEC, now );
}
Ejemplo n.º 6
0
void
tr_bandwidthSetPeer( tr_bandwidth * b, tr_peerIo * peer )
{
    assert( tr_isBandwidth( b ) );
    assert( ( peer == NULL ) || tr_isPeerIo( peer ) );

    b->peer = peer;
}
Ejemplo n.º 7
0
tr_bool
tr_isPeerIo( const tr_peerIo * io )
{
    return ( io != NULL )
        && ( io->magicNumber == MAGIC_NUMBER )
        && ( io->refCount >= 0 )
        && ( tr_isBandwidth( &io->bandwidth ) )
        && ( tr_isAddress( &io->addr ) );
}
Ejemplo n.º 8
0
void
tr_bandwidthRemovePeer( tr_bandwidth  * b,
                        tr_peerIo     * peerIo )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isPeerIo( peerIo ) );

    tr_ptrArrayRemoveSorted( b->peers, peerIo, comparePointers );
}
Ejemplo n.º 9
0
tr_bool
tr_bandwidthIsLimited( const tr_bandwidth  * b,
                       tr_direction          dir )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    return b->band[dir].isLimited;
}
Ejemplo n.º 10
0
double
tr_bandwidthGetDesiredSpeed( const tr_bandwidth  * b,
                             tr_direction          dir )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    return b->band[dir].desiredSpeed;
}
Ejemplo n.º 11
0
void
tr_bandwidthHonorParentLimits( tr_bandwidth  * b,
                               tr_direction    dir,
                               tr_bool         honorParentLimits )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    b->band[dir].honorParentLimits = honorParentLimits;
}
Ejemplo n.º 12
0
void
tr_bandwidthDestruct (tr_bandwidth * b)
{
  assert (tr_isBandwidth (b));

  tr_bandwidthSetParent (b, NULL);
  tr_ptrArrayDestruct (&b->children, NULL);

  memset (b, ~0, sizeof (tr_bandwidth));
}
Ejemplo n.º 13
0
void
tr_bandwidthSetDesiredSpeed( tr_bandwidth  * b,
                             tr_direction    dir,
                             double          desiredSpeed )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    b->band[dir].desiredSpeed = desiredSpeed; 
}
Ejemplo n.º 14
0
void
tr_bandwidthSetLimited( tr_bandwidth  * b,
                        tr_direction    dir,
                        tr_bool         isLimited )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    b->band[dir].isLimited = isLimited;
}
Ejemplo n.º 15
0
void
tr_bandwidthFree( tr_bandwidth * b )
{
    assert( tr_isBandwidth( b ) );

    tr_bandwidthSetParent( b, NULL );
    tr_ptrArrayFree( b->peers, NULL );
    tr_ptrArrayFree( b->children, NULL );
    b->magicNumber = 0xDEAD;
    tr_free( b );
}
Ejemplo n.º 16
0
static void
allocateBandwidth( tr_bandwidth  * b,
                   tr_priority_t   parent_priority,
                   tr_direction    dir,
                   unsigned int    period_msec,
                   tr_ptrArray   * peer_pool )
{
    tr_priority_t priority;

    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    /* set the available bandwidth */
    if( b->band[dir].isLimited )
    {
        const unsigned int nextPulseSpeed = b->band[dir].desiredSpeed_Bps;
        b->band[dir].bytesLeft = ( nextPulseSpeed * period_msec ) / 1000u;

#ifdef DEBUG_DIRECTION
        if( dir == DEBUG_DIRECTION )
                fprintf( stderr, "bandwidth %p currentPieceSpeed(%5.2f of %5.2f) desiredSpeed(%5.2f), allocating %d\n",
                         b, currentSpeed, tr_bandwidthGetRawSpeed( b, dir ), desiredSpeed,
                         b->band[dir].bytesLeft );
#endif
    }

    priority = MAX( parent_priority, b->priority );

    /* add this bandwidth's peer, if any, to the peer pool */
    if( b->peer != NULL ) {
        b->peer->priority = priority;
        tr_ptrArrayAppend( peer_pool, b->peer );
    }

#ifdef DEBUG_DIRECTION
if( ( dir == DEBUG_DIRECTION ) && ( n > 1 ) )
fprintf( stderr, "bandwidth %p has %d peers\n", b, n );
#endif

    /* traverse & repeat for the subtree */
    if( 1 ) {
        int i;
        struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayBase( &b->children );
        const int n = tr_ptrArraySize( &b->children );
        for( i=0; i<n; ++i )
            allocateBandwidth( children[i], priority, dir, period_msec, peer_pool );
    }
}
Ejemplo n.º 17
0
static void
allocateBandwidth( tr_bandwidth  * b,
                   tr_direction    dir,
                   int             period_msec,
                   tr_ptrArray   * peer_pool )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    /* set the available bandwidth */
    if( b->band[dir].isLimited )
    {
        const double desiredSpeed = b->band[dir].desiredSpeed;
        const double nextPulseSpeed = desiredSpeed;
        b->band[dir].bytesLeft = MAX( 0.0, nextPulseSpeed * 1024.0 * period_msec / 1000.0 );

#ifdef DEBUG_DIRECTION
        if( dir == DEBUG_DIRECTION )
                fprintf( stderr, "bandwidth %p currentPieceSpeed(%5.2f of %5.2f) desiredSpeed(%5.2f), allocating %5.2f\n",
                         b, currentSpeed, tr_bandwidthGetRawSpeed( b, dir ), desiredSpeed,
                         b->band[dir].bytesLeft/1024.0 );
#endif
    }

    /* traverse & repeat for the subtree */
    {
        int i;
        const int n = tr_ptrArraySize( b->peers );
        for( i=0; i<n; ++i )
            tr_ptrArrayAppend( peer_pool, tr_ptrArrayNth( b->peers, i ) );
    }

#ifdef DEBUG_DIRECTION
if( ( dir == DEBUG_DIRECTION ) && ( n > 1 ) )
fprintf( stderr, "bandwidth %p has %d peers\n", b, n );
#endif

    /* all children should reallocate too */
    if( 1 ) {
        int i, n=0;
        struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayPeek( b->children, &n );
        for( i=0; i<n; ++i )
            allocateBandwidth( children[i], dir, period_msec, peer_pool );
    }
}
Ejemplo n.º 18
0
unsigned int
tr_bandwidthClamp( const tr_bandwidth  * b,
                   tr_direction          dir,
                   unsigned int          byteCount )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    if( b )
    {
        if( b->band[dir].isLimited )
            byteCount = MIN( byteCount, b->band[dir].bytesLeft );

        if( b->parent && b->band[dir].honorParentLimits )
            byteCount = tr_bandwidthClamp( b->parent, dir, byteCount );
    }

    return byteCount;
}
Ejemplo n.º 19
0
static unsigned int
bandwidthClamp (const tr_bandwidth  * b,
                uint64_t              now,
                tr_direction          dir,
                unsigned int          byteCount)
{
  assert (tr_isBandwidth (b));
  assert (tr_isDirection (dir));

  if (b)
    {
      if (b->band[dir].isLimited)
        {
          byteCount = MIN (byteCount, b->band[dir].bytesLeft);

          /* if we're getting close to exceeding the speed limit,
           * clamp down harder on the bytes available */
          if (byteCount > 0)
            {
              double current;
              double desired;
              double r;

              if (now == 0)
                now = tr_time_msec ();

              current = tr_bandwidthGetRawSpeed_Bps (b, now, TR_DOWN);
              desired = tr_bandwidthGetDesiredSpeed_Bps (b, TR_DOWN);
              r = desired >= 1 ? current / desired : 0;

                   if (r > 1.0) byteCount = 0;
              else if (r > 0.9) byteCount *= 0.8;
              else if (r > 0.8) byteCount *= 0.9;
            }
        }

      if (b->parent && b->band[dir].honorParentLimits && (byteCount > 0))
        byteCount = bandwidthClamp (b->parent, now, dir, byteCount);
    }

  return byteCount;
}