(trunk libT) avoid some unnecessary memory fragmentation... for composited objects that have a tr_ptrArray, contain the tr_ptrArray directly rather than a pointer to one allocated elsewhere on the heap.

This commit is contained in:
Charles Kerr 2008-12-29 08:54:36 +00:00
parent db381a5e40
commit 427f639664
7 changed files with 176 additions and 160 deletions

View File

@ -98,8 +98,8 @@ struct tr_bandwidth
struct tr_bandwidth * parent;
int magicNumber;
tr_session * session;
tr_ptrArray * children; /* struct tr_bandwidth */
tr_ptrArray * peers; /* tr_peerIo */
tr_ptrArray children; /* struct tr_bandwidth */
tr_ptrArray peers; /* tr_peerIo */
};
/***
@ -130,8 +130,8 @@ tr_bandwidthNew( tr_session * session, tr_bandwidth * parent )
{
tr_bandwidth * b = tr_new0( tr_bandwidth, 1 );
b->session = session;
b->children = tr_ptrArrayNew( );
b->peers = tr_ptrArrayNew( );
b->children = TR_PTR_ARRAY_INIT;
b->peers = TR_PTR_ARRAY_INIT;
b->magicNumber = MAGIC_NUMBER;
b->band[TR_UP].honorParentLimits = TRUE;
b->band[TR_DOWN].honorParentLimits = TRUE;
@ -145,8 +145,8 @@ tr_bandwidthFree( tr_bandwidth * b )
assert( tr_isBandwidth( b ) );
tr_bandwidthSetParent( b, NULL );
tr_ptrArrayFree( b->peers, NULL );
tr_ptrArrayFree( b->children, NULL );
tr_ptrArrayDestruct( &b->peers, NULL );
tr_ptrArrayDestruct( &b->children, NULL );
b->magicNumber = 0xDEAD;
tr_free( b );
}
@ -166,7 +166,7 @@ tr_bandwidthSetParent( tr_bandwidth * b,
{
assert( tr_isBandwidth( b->parent ) );
tr_ptrArrayRemoveSorted( b->parent->children, b, comparePointers );
tr_ptrArrayRemoveSorted( &b->parent->children, b, comparePointers );
b->parent = NULL;
}
@ -175,7 +175,7 @@ tr_bandwidthSetParent( tr_bandwidth * b,
assert( tr_isBandwidth( parent ) );
assert( parent->parent != b );
tr_ptrArrayInsertSorted( parent->children, b, comparePointers );
tr_ptrArrayInsertSorted( &parent->children, b, comparePointers );
b->parent = parent;
}
}
@ -269,9 +269,9 @@ allocateBandwidth( tr_bandwidth * b,
/* traverse & repeat for the subtree */
{
int i;
const int n = tr_ptrArraySize( b->peers );
const int n = TR_PTR_ARRAY_LENGTH( &b->peers );
for( i=0; i<n; ++i )
tr_ptrArrayAppend( peer_pool, tr_ptrArrayNth( b->peers, i ) );
tr_ptrArrayAppend( peer_pool, tr_ptrArrayNth( &b->peers, i ) );
}
#ifdef DEBUG_DIRECTION
@ -281,8 +281,9 @@ fprintf( stderr, "bandwidth %p has %d peers\n", b, n );
/* all children should reallocate too */
if( 1 ) {
int i, n=0;
struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayPeek( b->children, &n );
int i;
struct tr_bandwidth ** children = (struct tr_bandwidth**) TR_PTR_ARRAY_DATA( &b->children );
const int n = TR_PTR_ARRAY_LENGTH( &b->children );
for( i=0; i<n; ++i )
allocateBandwidth( children[i], dir, period_msec, peer_pool );
}
@ -294,7 +295,7 @@ tr_bandwidthAllocate( tr_bandwidth * b,
int period_msec )
{
int i, n, peerCount;
tr_ptrArray * tmp;
tr_ptrArray tmp = TR_PTR_ARRAY_INIT;
struct tr_peerIo ** peers;
const uint64_t now = tr_date( );
const uint64_t cutoff = now + 100; /* 1/10th of a second */
@ -303,9 +304,8 @@ tr_bandwidthAllocate( tr_bandwidth * b,
/* allocateBandwidth() is a helper function with two purposes:
* 1. allocate bandwidth to b and its subtree
* 2. accumulate an array of all the peerIos from b and its subtree. */
tmp = tr_ptrArrayNew( );
allocateBandwidth( b, dir, period_msec, tmp );
peers = (struct tr_peerIo**) tr_ptrArrayPeek( tmp, &peerCount );
allocateBandwidth( b, dir, period_msec, &tmp );
peers = (struct tr_peerIo**) tr_ptrArrayPeek( &tmp, &peerCount );
/* Stop all peers from listening for the socket to be ready for IO.
* See "Second phase of IO" lower in this function for more info. */
@ -347,7 +347,7 @@ tr_bandwidthAllocate( tr_bandwidth * b,
tr_peerIoSetEnabled( peers[i], dir, TRUE );
/* cleanup */
tr_ptrArrayFree( tmp, NULL );
tr_ptrArrayDestruct( &tmp, NULL );
}
/***
@ -361,7 +361,7 @@ tr_bandwidthAddPeer( tr_bandwidth * b,
assert( tr_isBandwidth( b ) );
assert( tr_isPeerIo( peerIo ) );
tr_ptrArrayInsertSorted( b->peers, peerIo, comparePointers );
tr_ptrArrayInsertSorted( &b->peers, peerIo, comparePointers );
}
void
@ -371,7 +371,7 @@ tr_bandwidthRemovePeer( tr_bandwidth * b,
assert( tr_isBandwidth( b ) );
assert( tr_isPeerIo( peerIo ) );
tr_ptrArrayRemoveSorted( b->peers, peerIo, comparePointers );
tr_ptrArrayRemoveSorted( &b->peers, peerIo, comparePointers );
}
/***

View File

@ -326,14 +326,14 @@ tr_bencParse( const void * buf,
const uint8_t ** setme_end )
{
int err;
tr_ptrArray * parentStack = tr_ptrArrayNew( );
tr_ptrArray parentStack = TR_PTR_ARRAY_INIT;
top->type = 0; /* set to `uninitialized' */
err = tr_bencParseImpl( buf, end, top, parentStack, setme_end );
err = tr_bencParseImpl( buf, end, top, &parentStack, setme_end );
if( err )
tr_bencFree( top );
tr_ptrArrayFree( parentStack, NULL );
tr_ptrArrayDestruct( &parentStack, NULL );
return err;
}
@ -932,13 +932,13 @@ bencWalk( const tr_benc * top,
struct WalkFuncs * walkFuncs,
void * user_data )
{
tr_ptrArray * stack = tr_ptrArrayNew( );
tr_ptrArray stack = TR_PTR_ARRAY_INIT;
tr_ptrArrayAppend( stack, nodeNew( top ) );
tr_ptrArrayAppend( &stack, nodeNew( top ) );
while( !tr_ptrArrayEmpty( stack ) )
while( !tr_ptrArrayEmpty( &stack ) )
{
struct SaveNode * node = tr_ptrArrayBack( stack );
struct SaveNode * node = tr_ptrArrayBack( &stack );
const tr_benc * val;
if( !node->valIsVisited )
@ -955,7 +955,7 @@ bencWalk( const tr_benc * top,
{
if( isContainer( node->val ) )
walkFuncs->containerEndFunc( node->val, user_data );
tr_ptrArrayPop( stack );
tr_ptrArrayPop( &stack );
tr_free( node->children );
tr_free( node );
continue;
@ -973,14 +973,14 @@ bencWalk( const tr_benc * top,
case TYPE_LIST:
if( val != node->val )
tr_ptrArrayAppend( stack, nodeNew( val ) );
tr_ptrArrayAppend( &stack, nodeNew( val ) );
else
walkFuncs->listBeginFunc( val, user_data );
break;
case TYPE_DICT:
if( val != node->val )
tr_ptrArrayAppend( stack, nodeNew( val ) );
tr_ptrArrayAppend( &stack, nodeNew( val ) );
else
walkFuncs->dictBeginFunc( val, user_data );
break;
@ -992,7 +992,7 @@ bencWalk( const tr_benc * top,
}
}
tr_ptrArrayFree( stack, NULL );
tr_ptrArrayDestruct( &stack, NULL );
}
/****
@ -1087,7 +1087,7 @@ tr_bencFree( tr_benc * val )
{
if( val && val->type )
{
tr_ptrArray * freeme = tr_ptrArrayNew( );
tr_ptrArray a = TR_PTR_ARRAY_INIT;
struct WalkFuncs walkFuncs;
walkFuncs.intFunc = freeDummyFunc;
@ -1095,9 +1095,9 @@ tr_bencFree( tr_benc * val )
walkFuncs.dictBeginFunc = freeContainerBeginFunc;
walkFuncs.listBeginFunc = freeContainerBeginFunc;
walkFuncs.containerEndFunc = freeDummyFunc;
bencWalk( val, &walkFuncs, freeme );
bencWalk( val, &walkFuncs, &a );
tr_ptrArrayFree( freeme, tr_free );
tr_ptrArrayDestruct( &a, tr_free );
}
}

View File

@ -29,7 +29,7 @@
struct json_benc_data
{
tr_benc * top;
tr_ptrArray * stack;
tr_ptrArray stack;
char * key;
};
@ -39,10 +39,10 @@ getNode( struct json_benc_data * data )
tr_benc * parent;
tr_benc * node = NULL;
if( tr_ptrArrayEmpty( data->stack ) )
if( tr_ptrArrayEmpty( &data->stack ) )
parent = NULL;
else
parent = tr_ptrArrayBack( data->stack );
parent = tr_ptrArrayBack( &data->stack );
if( !parent )
node = data->top;
@ -71,21 +71,21 @@ callback( void * vdata,
case JSON_T_ARRAY_BEGIN:
node = getNode( data );
tr_bencInitList( node, 0 );
tr_ptrArrayAppend( data->stack, node );
tr_ptrArrayAppend( &data->stack, node );
break;
case JSON_T_ARRAY_END:
tr_ptrArrayPop( data->stack );
tr_ptrArrayPop( &data->stack );
break;
case JSON_T_OBJECT_BEGIN:
node = getNode( data );
tr_bencInitDict( node, 0 );
tr_ptrArrayAppend( data->stack, node );
tr_ptrArrayAppend( &data->stack, node );
break;
case JSON_T_OBJECT_END:
tr_ptrArrayPop( data->stack );
tr_ptrArrayPop( &data->stack );
break;
case JSON_T_FLOAT:
@ -148,7 +148,7 @@ tr_jsonParse( const void * vbuf,
data.key = NULL;
data.top = setme_benc;
data.stack = tr_ptrArrayNew( );
data.stack = TR_PTR_ARRAY_INIT;
checker = new_JSON_parser( &config );
while( ( buf != bufend ) && JSON_parser_char( checker, *buf ) )
@ -161,7 +161,7 @@ tr_jsonParse( const void * vbuf,
*setme_end = (const uint8_t*) buf;
delete_JSON_parser( checker );
tr_ptrArrayFree( data.stack, NULL );
tr_ptrArrayDestruct( &data.stack, NULL );
return err;
}

View File

@ -125,10 +125,10 @@ typedef struct
uint8_t hash[SHA_DIGEST_LENGTH];
int * pendingRequestCount;
tr_ptrArray * outgoingHandshakes; /* tr_handshake */
tr_ptrArray * pool; /* struct peer_atom */
tr_ptrArray * peers; /* tr_peer */
tr_ptrArray * webseeds; /* tr_webseed */
tr_ptrArray outgoingHandshakes; /* tr_handshake */
tr_ptrArray pool; /* struct peer_atom */
tr_ptrArray peers; /* tr_peer */
tr_ptrArray webseeds; /* tr_webseed */
tr_timer * reconnectTimer;
tr_timer * rechokeTimer;
tr_timer * refillTimer;
@ -142,9 +142,9 @@ Torrent;
struct tr_peerMgr
{
tr_session * session;
tr_ptrArray * torrents; /* Torrent */
tr_ptrArray * incomingHandshakes; /* tr_handshake */
tr_ptrArray * finishedHandshakes; /* tr_handshake */
tr_ptrArray torrents; /* Torrent */
tr_ptrArray incomingHandshakes; /* tr_handshake */
tr_ptrArray finishedHandshakes; /* tr_handshake */
tr_timer * bandwidthTimer;
};
@ -263,7 +263,7 @@ static Torrent*
getExistingTorrent( tr_peerMgr * manager,
const uint8_t * hash )
{
return (Torrent*) tr_ptrArrayFindSorted( manager->torrents,
return (Torrent*) tr_ptrArrayFindSorted( &manager->torrents,
hash,
torrentCompareToHash );
}
@ -292,15 +292,16 @@ getExistingPeer( Torrent * torrent,
assert( torrentIsLocked( torrent ) );
assert( addr );
return tr_ptrArrayFindSorted( torrent->peers, addr, peerCompareToAddr );
return tr_ptrArrayFindSorted( &torrent->peers, addr, peerCompareToAddr );
}
static struct peer_atom*
getExistingAtom( const Torrent * t,
const tr_address * addr )
{
Torrent * tt = (Torrent*)t;
assert( torrentIsLocked( t ) );
return tr_ptrArrayFindSorted( t->pool, addr, comparePeerAtomToAddress );
return tr_ptrArrayFindSorted( &tt->pool, addr, comparePeerAtomToAddress );
}
static tr_bool
@ -312,8 +313,8 @@ peerIsInUse( const Torrent * ct,
assert( torrentIsLocked ( t ) );
return getExistingPeer( t, addr )
|| getExistingHandshake( t->outgoingHandshakes, addr )
|| getExistingHandshake( t->manager->incomingHandshakes, addr );
|| getExistingHandshake( &t->outgoingHandshakes, addr )
|| getExistingHandshake( &t->manager->incomingHandshakes, addr );
}
static tr_peer*
@ -339,7 +340,7 @@ getPeer( Torrent * torrent,
if( peer == NULL )
{
peer = peerConstructor( torrent->tor, addr );
tr_ptrArrayInsertSorted( torrent->peers, peer, peerCompare );
tr_ptrArrayInsertSorted( &torrent->peers, peer, peerCompare );
}
return peer;
@ -380,7 +381,7 @@ removePeer( Torrent * t,
assert( atom );
atom->time = time( NULL );
removed = tr_ptrArrayRemoveSorted( t->peers, peer, peerCompare );
removed = tr_ptrArrayRemoveSorted( &t->peers, peer, peerCompare );
assert( removed == peer );
peerDestructor( removed );
}
@ -388,8 +389,8 @@ removePeer( Torrent * t,
static void
removeAllPeers( Torrent * t )
{
while( !tr_ptrArrayEmpty( t->peers ) )
removePeer( t, tr_ptrArrayNth( t->peers, 0 ) );
while( !tr_ptrArrayEmpty( &t->peers ) )
removePeer( t, tr_ptrArrayNth( &t->peers, 0 ) );
}
static void
@ -400,10 +401,9 @@ torrentDestructor( void * vt )
assert( t );
assert( !t->isRunning );
assert( t->peers );
assert( torrentIsLocked( t ) );
assert( tr_ptrArrayEmpty( t->outgoingHandshakes ) );
assert( tr_ptrArrayEmpty( t->peers ) );
assert( tr_ptrArrayEmpty( &t->outgoingHandshakes ) );
assert( tr_ptrArrayEmpty( &t->peers ) );
memcpy( hash, t->hash, SHA_DIGEST_LENGTH );
@ -411,10 +411,10 @@ torrentDestructor( void * vt )
tr_timerFree( &t->rechokeTimer );
tr_timerFree( &t->refillTimer );
tr_ptrArrayFree( t->webseeds, (PtrArrayForeachFunc)tr_webseedFree );
tr_ptrArrayFree( t->pool, (PtrArrayForeachFunc)tr_free );
tr_ptrArrayFree( t->outgoingHandshakes, NULL );
tr_ptrArrayFree( t->peers, NULL );
tr_ptrArrayDestruct( &t->webseeds, (PtrArrayForeachFunc)tr_webseedFree );
tr_ptrArrayDestruct( &t->pool, (PtrArrayForeachFunc)tr_free );
tr_ptrArrayDestruct( &t->outgoingHandshakes, NULL );
tr_ptrArrayDestruct( &t->peers, NULL );
tr_free( t->pendingRequestCount );
tr_free( t );
@ -434,18 +434,17 @@ torrentConstructor( tr_peerMgr * manager,
t = tr_new0( Torrent, 1 );
t->manager = manager;
t->tor = tor;
t->pool = tr_ptrArrayNew( );
t->peers = tr_ptrArrayNew( );
t->webseeds = tr_ptrArrayNew( );
t->outgoingHandshakes = tr_ptrArrayNew( );
t->pool = TR_PTR_ARRAY_INIT;
t->peers = TR_PTR_ARRAY_INIT;
t->webseeds = TR_PTR_ARRAY_INIT;
t->outgoingHandshakes = TR_PTR_ARRAY_INIT;
memcpy( t->hash, tor->info.hash, SHA_DIGEST_LENGTH );
for( i = 0; i < tor->info.webseedCount; ++i )
{
tr_webseed * w =
tr_webseedNew( tor, tor->info.webseeds[i], peerCallbackFunc,
t );
tr_ptrArrayAppend( t->webseeds, w );
tr_webseedNew( tor, tor->info.webseeds[i], peerCallbackFunc, t );
tr_ptrArrayAppend( &t->webseeds, w );
}
return t;
@ -461,9 +460,9 @@ tr_peerMgrNew( tr_session * session )
tr_peerMgr * m = tr_new0( tr_peerMgr, 1 );
m->session = session;
m->torrents = tr_ptrArrayNew( );
m->incomingHandshakes = tr_ptrArrayNew( );
m->finishedHandshakes = tr_ptrArrayNew( );
m->torrents = TR_PTR_ARRAY_INIT;
m->incomingHandshakes = TR_PTR_ARRAY_INIT;
m->finishedHandshakes = TR_PTR_ARRAY_INIT;
m->bandwidthTimer = tr_timerNew( session, bandwidthPulse, m, BANDWIDTH_PERIOD_MSEC );
return m;
}
@ -479,18 +478,18 @@ tr_peerMgrFree( tr_peerMgr * manager )
/* free the handshakes. Abort invokes handshakeDoneCB(), which removes
* the item from manager->handshakes, so this is a little roundabout... */
while( !tr_ptrArrayEmpty( manager->incomingHandshakes ) )
tr_handshakeAbort( tr_ptrArrayNth( manager->incomingHandshakes, 0 ) );
while( !tr_ptrArrayEmpty( &manager->incomingHandshakes ) )
tr_handshakeAbort( tr_ptrArrayNth( &manager->incomingHandshakes, 0 ) );
tr_ptrArrayFree( manager->incomingHandshakes, NULL );
tr_ptrArrayDestruct( &manager->incomingHandshakes, NULL );
while(( handshake = tr_ptrArrayPop( manager->finishedHandshakes )))
while(( handshake = tr_ptrArrayPop( &manager->finishedHandshakes )))
tr_handshakeFree( handshake );
tr_ptrArrayFree( manager->finishedHandshakes, NULL );
tr_ptrArrayDestruct( &manager->finishedHandshakes, NULL );
/* free the torrents. */
tr_ptrArrayFree( manager->torrents, torrentDestructor );
tr_ptrArrayDestruct( &manager->torrents, torrentDestructor );
managerUnlock( manager );
tr_free( manager );
@ -505,7 +504,7 @@ getConnectedPeers( Torrent * t, int * setmeCount )
assert( torrentIsLocked( t ) );
peers = (tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
peers = (tr_peer **) tr_ptrArrayPeek( &t->peers, &peerCount );
ret = tr_new( tr_peer *, peerCount );
for( i = connectionCount = 0; i < peerCount; ++i )
@ -758,7 +757,7 @@ getPeersUploadingToClient( Torrent * t,
int j;
int peerCount = 0;
int retCount = 0;
tr_peer ** peers = (tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
tr_peer ** peers = (tr_peer **) tr_ptrArrayPeek( &t->peers, &peerCount );
tr_peer ** ret = tr_new( tr_peer *, peerCount );
j = 0; /* this is a temporary test to make sure we walk through all the peers */
@ -812,8 +811,8 @@ refillPulse( void * vtorrent )
blockIterator = blockIteratorNew( t );
peers = getPeersUploadingToClient( t, &peerCount );
webseedCount = tr_ptrArraySize( t->webseeds );
webseeds = tr_memdup( tr_ptrArrayBase( t->webseeds ),
webseedCount = tr_ptrArraySize( &t->webseeds );
webseeds = tr_memdup( tr_ptrArrayBase( &t->webseeds ),
webseedCount * sizeof( tr_webseed* ) );
while( ( webseedCount || peerCount )
@ -1182,7 +1181,7 @@ ensureAtomExists( Torrent * t,
a->flags = flags;
a->from = from;
tordbg( t, "got a new atom: %s", tr_peerIoAddrStr( &a->addr, a->port ) );
tr_ptrArrayInsertSorted( t->pool, a, comparePeerAtoms );
tr_ptrArrayInsertSorted( &t->pool, a, comparePeerAtoms );
}
}
@ -1195,7 +1194,7 @@ getMaxPeerCount( const tr_torrent * tor )
static int
getPeerCount( const Torrent * t )
{
return tr_ptrArraySize( t->peers ) + tr_ptrArraySize( t->outgoingHandshakes );
return tr_ptrArraySize( &t->peers ) + tr_ptrArraySize( &t->outgoingHandshakes );
}
/* FIXME: this is kind of a mess. */
@ -1222,10 +1221,10 @@ myHandshakeDoneCB( tr_handshake * handshake,
: NULL;
if( tr_peerIoIsIncoming ( io ) )
ours = tr_ptrArrayRemoveSorted( manager->incomingHandshakes,
ours = tr_ptrArrayRemoveSorted( &manager->incomingHandshakes,
handshake, handshakeCompare );
else if( t )
ours = tr_ptrArrayRemoveSorted( t->outgoingHandshakes,
ours = tr_ptrArrayRemoveSorted( &t->outgoingHandshakes,
handshake, handshakeCompare );
else
ours = handshake;
@ -1296,7 +1295,7 @@ myHandshakeDoneCB( tr_handshake * handshake,
}
if( !success )
tr_ptrArrayAppend( manager->finishedHandshakes, handshake );
tr_ptrArrayAppend( &manager->finishedHandshakes, handshake );
if( t )
torrentUnlock( t );
@ -1317,7 +1316,7 @@ tr_peerMgrAddIncoming( tr_peerMgr * manager,
tr_dbg( "Banned IP address \"%s\" tried to connect to us", tr_ntop_non_ts( addr ) );
tr_netClose( socket );
}
else if( getExistingHandshake( manager->incomingHandshakes, addr ) )
else if( getExistingHandshake( &manager->incomingHandshakes, addr ) )
{
tr_netClose( socket );
}
@ -1333,7 +1332,7 @@ tr_peerMgrAddIncoming( tr_peerMgr * manager,
myHandshakeDoneCB,
manager );
tr_ptrArrayInsertSorted( manager->incomingHandshakes, handshake,
tr_ptrArrayInsertSorted( &manager->incomingHandshakes, handshake,
handshakeCompare );
}
@ -1456,7 +1455,7 @@ tr_peerMgrSetBlame( tr_peerMgr * manager,
assert( torrentIsLocked( t ) );
peers = (tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
peers = (tr_peer **) tr_ptrArrayPeek( &t->peers, &peerCount );
for( i = 0; i < peerCount; ++i )
{
tr_peer * peer = peers[i];
@ -1508,7 +1507,6 @@ tr_peerMgrGetPeers( tr_peerMgr * manager,
tr_pex ** setme_pex,
uint8_t af)
{
int peerCount = 0;
int peersReturning = 0;
const Torrent * t;
@ -1522,7 +1520,8 @@ tr_peerMgrGetPeers( tr_peerMgr * manager,
else
{
int i;
const tr_peer ** peers = (const tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
const tr_peer ** peers = (const tr_peer**) TR_PTR_ARRAY_DATA( &t->peers );
const int peerCount = TR_PTR_ARRAY_LENGTH( &t->peers );
/* for now, this will waste memory on torrents that have both
* ipv6 and ipv4 peers */
tr_pex * pex = tr_new( tr_pex, peerCount );
@ -1591,7 +1590,7 @@ tr_peerMgrStartTorrent( tr_peerMgr * manager,
rechokePulse( t );
if( !tr_ptrArrayEmpty( t->webseeds ) )
if( !tr_ptrArrayEmpty( &t->webseeds ) )
refillSoon( t );
}
@ -1608,13 +1607,13 @@ stopTorrent( Torrent * t )
tr_timerFree( &t->reconnectTimer );
/* disconnect the peers. */
tr_ptrArrayForeach( t->peers, (PtrArrayForeachFunc)peerDestructor );
tr_ptrArrayClear( t->peers );
tr_ptrArrayForeach( &t->peers, (PtrArrayForeachFunc)peerDestructor );
tr_ptrArrayClear( &t->peers );
/* disconnect the handshakes. handshakeAbort calls handshakeDoneCB(),
* which removes the handshake from t->outgoingHandshakes... */
while( !tr_ptrArrayEmpty( t->outgoingHandshakes ) )
tr_handshakeAbort( tr_ptrArrayNth( t->outgoingHandshakes, 0 ) );
while( !tr_ptrArrayEmpty( &t->outgoingHandshakes ) )
tr_handshakeAbort( tr_ptrArrayNth( &t->outgoingHandshakes, 0 ) );
}
void
@ -1640,7 +1639,7 @@ tr_peerMgrAddTorrent( tr_peerMgr * manager,
assert( getExistingTorrent( manager, tor->info.hash ) == NULL );
t = torrentConstructor( manager, tor );
tr_ptrArrayInsertSorted( manager->torrents, t, torrentCompare );
tr_ptrArrayInsertSorted( &manager->torrents, t, torrentCompare );
managerUnlock( manager );
}
@ -1656,7 +1655,7 @@ tr_peerMgrRemoveTorrent( tr_peerMgr * manager,
t = getExistingTorrent( manager, torrentHash );
assert( t );
stopTorrent( t );
tr_ptrArrayRemoveSorted( manager->torrents, t, torrentCompare );
tr_ptrArrayRemoveSorted( &manager->torrents, t, torrentCompare );
torrentDestructor( t );
managerUnlock( manager );
@ -1682,7 +1681,8 @@ tr_peerMgrTorrentAvailability( const tr_peerMgr * manager,
tor = t->tor;
interval = tor->info.pieceCount / (float)tabCount;
isSeed = tor && ( tr_cpGetStatus ( tor->completion ) == TR_SEED );
peers = (const tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
peers = (const tr_peer **) TR_PTR_ARRAY_DATA( &t->peers );
peerCount = TR_PTR_ARRAY_LENGTH( &t->peers );
memset( tab, 0, tabCount );
@ -1734,7 +1734,7 @@ tr_peerMgrHasConnections( const tr_peerMgr * manager,
managerLock( manager );
t = getExistingTorrent( (tr_peerMgr*)manager, torrentHash );
ret = t && ( !tr_ptrArrayEmpty( t->peers ) || !tr_ptrArrayEmpty( t->webseeds ) );
ret = t && ( !tr_ptrArrayEmpty( &t->peers ) || !tr_ptrArrayEmpty( &t->webseeds ) );
managerUnlock( manager );
return ret;
@ -1759,9 +1759,10 @@ tr_peerMgrTorrentStats( const tr_peerMgr * manager,
managerLock( manager );
t = getExistingTorrent( (tr_peerMgr*)manager, torrentHash );
peers = (const tr_peer **) tr_ptrArrayPeek( t->peers, &size );
peers = (const tr_peer **) TR_PTR_ARRAY_DATA( &t->peers );
size = TR_PTR_ARRAY_LENGTH( &t->peers );
*setmePeersKnown = tr_ptrArraySize( t->pool );
*setmePeersKnown = tr_ptrArraySize( &t->pool );
*setmePeersConnected = 0;
*setmeSeedsConnected = 0;
*setmePeersGettingFromUs = 0;
@ -1793,7 +1794,8 @@ tr_peerMgrTorrentStats( const tr_peerMgr * manager,
++*setmeSeedsConnected;
}
webseeds = (const tr_webseed **) tr_ptrArrayPeek( t->webseeds, &size );
webseeds = (const tr_webseed**) TR_PTR_ARRAY_DATA( &t->webseeds );
size = TR_PTR_ARRAY_LENGTH( &t->webseeds );
for( i=0; i<size; ++i )
if( tr_webseedIsActive( webseeds[i] ) )
++*setmeWebseedsSendingToUs;
@ -1815,8 +1817,8 @@ tr_peerMgrWebSpeeds( const tr_peerMgr * manager,
managerLock( manager );
t = getExistingTorrent( (tr_peerMgr*)manager, torrentHash );
webseeds = (const tr_webseed**) tr_ptrArrayPeek( t->webseeds,
&webseedCount );
webseeds = (const tr_webseed**) TR_PTR_ARRAY_DATA( &t->webseeds );
webseedCount = TR_PTR_ARRAY_LENGTH( &t->webseeds );
assert( webseedCount == t->tor->info.webseedCount );
ret = tr_new0( float, webseedCount );
@ -2014,7 +2016,7 @@ rechoke( Torrent * t )
{
int n;
struct ChokeData * c;
tr_ptrArray * randPool = tr_ptrArrayNew( );
tr_ptrArray randPool = TR_PTR_ARRAY_INIT;
for( ; i<size; ++i )
{
@ -2025,18 +2027,18 @@ rechoke( Torrent * t )
if( isNew( peer ) ) x *= 3;
if( isSame( peer ) ) x *= 3;
for( y=0; y<x; ++y )
tr_ptrArrayAppend( randPool, &choke[i] );
tr_ptrArrayAppend( &randPool, &choke[i] );
}
}
if(( n = tr_ptrArraySize( randPool )))
if(( n = tr_ptrArraySize( &randPool )))
{
c = tr_ptrArrayNth( randPool, tr_cryptoWeakRandInt( n ));
c = tr_ptrArrayNth( &randPool, tr_cryptoWeakRandInt( n ));
c->doUnchoke = 1;
t->optimistic = c->peer;
}
tr_ptrArrayFree( randPool, NULL );
tr_ptrArrayDestruct( &randPool, NULL );
}
for( i=0; i<size; ++i )
@ -2133,7 +2135,7 @@ static tr_peer **
getPeersToClose( Torrent * t, int * setmeSize )
{
int i, peerCount, outsize;
tr_peer ** peers = (tr_peer**) tr_ptrArrayPeek( t->peers, &peerCount );
tr_peer ** peers = (tr_peer**) tr_ptrArrayPeek( &t->peers, &peerCount );
struct tr_peer ** ret = tr_new( tr_peer *, peerCount );
assert( torrentIsLocked( t ) );
@ -2219,7 +2221,7 @@ getPeerCandidates( Torrent * t, int * setmeSize )
assert( torrentIsLocked( t ) );
atoms = (struct peer_atom**) tr_ptrArrayPeek( t->pool, &atomCount );
atoms = (struct peer_atom**) tr_ptrArrayPeek( &t->pool, &atomCount );
ret = tr_new( struct peer_atom*, atomCount );
for( i = retCount = 0; i < atomCount; ++i )
{
@ -2298,7 +2300,7 @@ reconnectPulse( void * vtorrent )
tordbg( t, "reconnect pulse for [%s]: %d bad connections, "
"%d connection candidates, %d atoms, max per pulse is %d",
t->tor->info.name, nBad, nCandidates,
tr_ptrArraySize( t->pool ),
tr_ptrArraySize( &t->pool ),
(int)MAX_RECONNECTIONS_PER_PULSE );
/* disconnect some peers.
@ -2345,7 +2347,7 @@ reconnectPulse( void * vtorrent )
++newConnectionsThisSecond;
tr_ptrArrayInsertSorted( t->outgoingHandshakes, handshake,
tr_ptrArrayInsertSorted( &t->outgoingHandshakes, handshake,
handshakeCompare );
}
@ -2370,15 +2372,15 @@ reconnectPulse( void * vtorrent )
static void
pumpAllPeers( tr_peerMgr * mgr )
{
const int torrentCount = tr_ptrArraySize( mgr->torrents );
const int torrentCount = tr_ptrArraySize( &mgr->torrents );
int i, j;
for( i=0; i<torrentCount; ++i )
{
Torrent * t = tr_ptrArrayNth( mgr->torrents, i );
for( j=0; j<tr_ptrArraySize( t->peers ); ++j )
Torrent * t = tr_ptrArrayNth( &mgr->torrents, i );
for( j=0; j<tr_ptrArraySize( &t->peers ); ++j )
{
tr_peer * peer = tr_ptrArrayNth( t->peers, j );
tr_peer * peer = tr_ptrArrayNth( &t->peers, j );
tr_peerMsgsPulse( peer->msgs );
}
}
@ -2399,7 +2401,7 @@ bandwidthPulse( void * vmgr )
tr_bandwidthAllocate( mgr->session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC );
/* free all the finished handshakes */
while(( handshake = tr_ptrArrayPop( mgr->finishedHandshakes )))
while(( handshake = tr_ptrArrayPop( &mgr->finishedHandshakes )))
tr_handshakeFree( handshake );
managerUnlock( mgr );

View File

@ -19,23 +19,27 @@
#define GROW 32
struct tr_ptrArray
const tr_ptrArray TR_PTR_ARRAY_INIT = { NULL, 0, 0 };
void
tr_ptrArrayDestruct( tr_ptrArray * p, PtrArrayForeachFunc func )
{
void ** items;
int n_items;
int n_alloc;
};
assert( p );
assert( p->items || !p->n_items );
if( func )
tr_ptrArrayForeach( p, func );
tr_free( p->items );
memset( p, ~0, sizeof( tr_ptrArray ) );
}
tr_ptrArray*
tr_ptrArrayNew( void )
{
tr_ptrArray * p;
p = tr_new( tr_ptrArray, 1 );
p->n_items = 0;
p->n_alloc = 0;
p->items = NULL;
tr_ptrArray * p = tr_new( tr_ptrArray, 1 );
*p = TR_PTR_ARRAY_INIT;
return p;
}
@ -69,13 +73,7 @@ void
tr_ptrArrayFree( tr_ptrArray * t,
PtrArrayForeachFunc func )
{
assert( t );
assert( t->items || !t->n_items );
if( func )
tr_ptrArrayForeach( t, func );
tr_free( t->items );
tr_ptrArrayDestruct( t, func );
tr_free( t );
}

View File

@ -32,10 +32,23 @@
/**
* A simple pointer array that resizes itself dynamically.
*/
typedef struct tr_ptrArray tr_ptrArray;
typedef struct tr_ptrArray
{
void ** items;
int n_items;
int n_alloc;
}
tr_ptrArray;
#define TR_PTR_ARRAY_DATA( A ) ((A)->items)
#define TR_PTR_ARRAY_LENGTH( A ) ((A)->n_items)
typedef void ( *PtrArrayForeachFunc )( void * );
extern const tr_ptrArray TR_PTR_ARRAY_INIT;
void tr_ptrArrayDestruct( tr_ptrArray*, PtrArrayForeachFunc func );
tr_ptrArray * tr_ptrArrayNew( void );
tr_ptrArray * tr_ptrArrayDup( tr_ptrArray* );

View File

@ -1841,6 +1841,7 @@ addDirtyFile( const char * root,
{
char * tmp;
tr_ptrArrayInsertSorted( dirtyFolders, tr_strdup( dir ), vstrcmp );
tmp = tr_dirname( dir );
tr_free( dir );
dir = tmp;
@ -1895,9 +1896,9 @@ deleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
int i, n;
char ** s;
tr_file_index_t f;
tr_ptrArray * torrentFiles = tr_ptrArrayNew( );
tr_ptrArray * folders = tr_ptrArrayNew( );
tr_ptrArray * dirtyFolders = tr_ptrArrayNew( ); /* dirty == contains non-torrent files */
tr_ptrArray torrentFiles = TR_PTR_ARRAY_INIT;
tr_ptrArray folders = TR_PTR_ARRAY_INIT;
tr_ptrArray dirtyFolders = TR_PTR_ARRAY_INIT; /* dirty == contains non-torrent files */
const char * firstFile = tor->info.files[0].name;
const char * cpch = strchr( firstFile, TR_PATH_DELIMITER );
@ -1905,10 +1906,10 @@ deleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
char * root = tr_buildPath( tor->downloadDir, tmp, NULL );
for( f=0; f<tor->info.fileCount; ++f )
tr_ptrArrayInsertSorted( torrentFiles, tor->info.files[f].name, vstrcmp );
tr_ptrArrayInsertSorted( &torrentFiles, tor->info.files[f].name, vstrcmp );
/* build the set of folders and dirtyFolders */
walkLocalData( tor, root, root, NULL, torrentFiles, folders, dirtyFolders );
walkLocalData( tor, root, root, NULL, &torrentFiles, &folders, &dirtyFolders );
/* close all the files because we're about to delete them */
for( f=0; f<tor->info.fileCount; ++f ) {
@ -1918,12 +1919,12 @@ deleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
}
/* try to remove entire folders first, so that the recycle bin will be tidy */
s = (char**) tr_ptrArrayPeek( folders, &n );
s = (char**) tr_ptrArrayPeek( &folders, &n );
for( i=0; i<n; ++i )
if( tr_ptrArrayFindSorted( dirtyFolders, s[i], vstrcmp ) == NULL )
if( tr_ptrArrayFindSorted( &dirtyFolders, s[i], vstrcmp ) == NULL )
fileFunc( s[i] );
/* now blow away any remaining torrent files, such torrent files in dirty folders */
/* now blow away any remaining torrent files, such as torrent files in dirty folders */
for( f=0; f<tor->info.fileCount; ++f ) {
char * path = tr_buildPath( tor->downloadDir, tor->info.files[f].name, NULL );
fileFunc( path );
@ -1934,21 +1935,21 @@ deleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
* Work from deepest to shallowest s.t. lower folders
* won't prevent the upper folders from being deleted */
{
tr_ptrArray * cleanFolders = tr_ptrArrayNew( );
s = (char**) tr_ptrArrayPeek( folders, &n );
tr_ptrArray cleanFolders = TR_PTR_ARRAY_INIT;
s = (char**) tr_ptrArrayPeek( &folders, &n );
for( i=0; i<n; ++i )
if( tr_ptrArrayFindSorted( dirtyFolders, s[i], vstrcmp ) == NULL )
tr_ptrArrayInsertSorted( cleanFolders, s[i], compareLongestFirst );
s = (char**) tr_ptrArrayPeek( cleanFolders, &n );
if( tr_ptrArrayFindSorted( &dirtyFolders, s[i], vstrcmp ) == NULL )
tr_ptrArrayInsertSorted( &cleanFolders, s[i], compareLongestFirst );
s = (char**) tr_ptrArrayPeek( &cleanFolders, &n );
for( i=0; i<n; ++i )
fileFunc( s[i] );
tr_ptrArrayFree( cleanFolders, NULL );
tr_ptrArrayDestruct( &cleanFolders, NULL );
}
/* cleanup */
tr_ptrArrayFree( dirtyFolders, tr_free );
tr_ptrArrayFree( folders, tr_free );
tr_ptrArrayFree( torrentFiles, NULL );
tr_ptrArrayDestruct( &dirtyFolders, tr_free );
tr_ptrArrayDestruct( &folders, tr_free );
tr_ptrArrayDestruct( &torrentFiles, NULL );
tr_free( root );
tr_free( tmp );
}
@ -1962,7 +1963,9 @@ tr_torrentDeleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
if( tor->info.fileCount > 1 )
deleteLocalData( tor, fileFunc );
else {
/* torrent only has one file */
char * path = tr_buildPath( tor->downloadDir, tor->info.files[0].name, NULL );
tr_fdFileClose( path );
fileFunc( path );
tr_free( path );
}