#220: lazy bitfields

This commit is contained in:
Charles Kerr 2008-08-16 21:06:57 +00:00
parent 6111a82a5f
commit d06f101e57
12 changed files with 112 additions and 34 deletions

View File

@ -271,6 +271,7 @@ main( int argc, char ** argv )
natTraversal, /* nat enabled */
peerPort,
encryptionMode,
TR_DEFAULT_LAZY_BITFIELD_ENABLED,
uploadLimit >= 0,
uploadLimit,
downloadLimit >= 0,

View File

@ -36,6 +36,7 @@ static char myConfigFilename[MAX_PATH_LENGTH];
#define KEY_BLOCKLIST "blocklist-enabled"
#define KEY_DOWNLOAD_DIR "download-dir"
#define KEY_ENCRYPTION "encryption"
#define KEY_LAZY_BITFIELD "lazy-bitfield-enabled"
#define KEY_PEER_LIMIT "max-peers-global"
#define KEY_PEER_PORT "peer-port"
#define KEY_PORT_FORWARDING "port-forwarding-enabled"
@ -151,6 +152,7 @@ session_init( const char * configDir, const char * downloadDir,
int fwdEnabled = -1;
int upLimit=-1, upLimited=-1, downLimit=-1, downLimited=-1;
int encryption = -1;
int useLazyBitfield = -1;
tr_ctor * ctor;
tr_torrent ** torrents;
@ -173,6 +175,7 @@ session_init( const char * configDir, const char * downloadDir,
getConfigInt( dict, KEY_DSPEED_ENABLED, &downLimited, FALSE );
getConfigInt( dict, KEY_USPEED, &upLimit, 100 );
getConfigInt( dict, KEY_USPEED_ENABLED, &upLimited, FALSE );
getConfigInt( dict, KEY_LAZY_BITFIELD, &useLazyBitfield, TR_DEFAULT_LAZY_BITFIELD_ENABLED );
getConfigInt( dict, KEY_PEER_LIMIT, &peers, TR_DEFAULT_GLOBAL_PEER_LIMIT );
getConfigInt( dict, KEY_BLOCKLIST, &blocklistEnabled, TR_DEFAULT_BLOCKLIST_ENABLED );
getConfigInt( dict, KEY_RPC_PORT, &rpcPort, TR_DEFAULT_RPC_PORT );
@ -190,6 +193,7 @@ session_init( const char * configDir, const char * downloadDir,
mySession = tr_sessionInitFull( configDir, "daemon", downloadDir,
pexEnabled, fwdEnabled, peerPort,
encryption,
useLazyBitfield,
upLimited, upLimit,
downLimited, downLimit,
peers,

View File

@ -421,6 +421,7 @@ main( int argc, char ** argv )
pref_flag_get( PREF_KEY_PORT_FORWARDING ),
pref_int_get( PREF_KEY_PORT ),
pref_int_get( PREF_KEY_ENCRYPTION ),
pref_flag_get( PREF_KEY_LAZY_BITFIELD ),
pref_flag_get( PREF_KEY_UL_LIMIT_ENABLED ),
pref_int_get( PREF_KEY_UL_LIMIT ),
pref_flag_get( PREF_KEY_DL_LIMIT_ENABLED ),

View File

@ -99,6 +99,7 @@ tr_prefs_init_global( void )
pref_flag_set_default ( PREF_KEY_PEX, TR_DEFAULT_PEX_ENABLED );
pref_flag_set_default ( PREF_KEY_ASKQUIT, TRUE );
pref_flag_set_default ( PREF_KEY_ENCRYPTION, TR_ENCRYPTION_PREFERRED );
pref_flag_set_default ( PREF_KEY_LAZY_BITFIELD, TR_DEFAULT_LAZY_BITFIELD_ENABLED );
pref_int_set_default ( PREF_KEY_MSGLEVEL, TR_MSG_INF );

View File

@ -40,6 +40,7 @@ GtkWidget * tr_prefs_dialog_new( GObject * core, GtkWindow * parent );
#define PREF_KEY_ASKQUIT "prompt-before-exit"
#define PREF_KEY_ENCRYPTION "encryption"
#define PREF_KEY_MSGLEVEL "debug-message-level"
#define PREF_KEY_LAZY_BITFIELD "lazy-bitfield-enabled"
#define PREF_KEY_SORT_MODE "sort-mode"
#define PREF_KEY_SORT_REVERSED "sort-reversed"
#define PREF_KEY_MINIMAL_VIEW "minimal-view"

View File

@ -43,6 +43,7 @@
#include "fdlimit.h"
#include "natpmp.h"
#include "net.h"
#include "peer-io.h"
#include "platform.h"
#include "utils.h"
@ -122,10 +123,12 @@ createSocket( int type, int priority )
if( fd >= 0 )
fd = makeSocketNonBlocking( fd );
#if 0
if( fd >= 0 ) {
const int buffsize = 1500*3; /* 3x MTU for most ethernet/wireless */
setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof( buffsize ) );
}
#endif
return fd;
}
@ -138,9 +141,7 @@ tr_netOpenTCP( const struct in_addr * addr, tr_port_t port, int priority )
const int type = SOCK_STREAM;
if( ( s = createSocket( type, priority ) ) < 0 )
{
return -1;
}
memset( &sock, 0, sizeof( sock ) );
sock.sin_family = AF_INET;
@ -161,6 +162,9 @@ tr_netOpenTCP( const struct in_addr * addr, tr_port_t port, int priority )
s = -1;
}
tr_deepLog( __FILE__, __LINE__, NULL, "New OUTGOING connection %d (%s)",
s, tr_peerIoAddrStr( addr, port ) );
return s;
}

View File

@ -23,6 +23,7 @@
#include "transmission.h"
#include "bencode.h"
#include "completion.h"
#include "crypto.h"
#include "inout.h"
#include "peer-io.h"
#include "peer-mgr.h"
@ -89,7 +90,11 @@ enum
/* used in lowering the outMessages queue period */
IMMEDIATE_PRIORITY_INTERVAL_SECS = 0,
HIGH_PRIORITY_INTERVAL_SECS = 2,
LOW_PRIORITY_INTERVAL_SECS = 20
LOW_PRIORITY_INTERVAL_SECS = 20,
/* number of pieces to remove from the bitfield when
* lazy bitfields are turned on */
LAZY_PIECE_COUNT = 26
};
/**
@ -295,7 +300,7 @@ struct tr_peermsgs
tr_peer * info;
tr_handle * handle;
tr_session * session;
tr_torrent * torrent;
tr_peerIo * io;
@ -381,14 +386,14 @@ protocolSendRequest( tr_peermsgs * msgs, const struct peer_request * req )
tr_peerIo * io = msgs->io;
struct evbuffer * out = msgs->outMessages;
dbgmsg( msgs, "requesting %u:%u->%u", req->index, req->offset, req->length );
tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 3*sizeof(uint32_t) );
tr_peerIoWriteUint8 ( io, out, BT_REQUEST );
tr_peerIoWriteUint32( io, out, req->index );
tr_peerIoWriteUint32( io, out, req->offset );
tr_peerIoWriteUint32( io, out, req->length );
dbgmsg( msgs, "requesting %u:%u->%u... outMessage size is now %d",
req->index, req->offset, req->length, (int)EVBUFFER_LENGTH(out) );
pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS );
dbgmsg( msgs, "outMessage size is now %d", (int)EVBUFFER_LENGTH(out) );
}
static void
@ -397,14 +402,14 @@ protocolSendCancel( tr_peermsgs * msgs, const struct peer_request * req )
tr_peerIo * io = msgs->io;
struct evbuffer * out = msgs->outMessages;
dbgmsg( msgs, "cancelling %u:%u->%u", req->index, req->offset, req->length );
tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 3*sizeof(uint32_t) );
tr_peerIoWriteUint8 ( io, out, BT_CANCEL );
tr_peerIoWriteUint32( io, out, req->index );
tr_peerIoWriteUint32( io, out, req->offset );
tr_peerIoWriteUint32( io, out, req->length );
dbgmsg( msgs, "cancelling %u:%u->%u... outMessage size is now %d",
req->index, req->offset, req->length, (int)EVBUFFER_LENGTH(out) );
pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
dbgmsg( msgs, "outMessage size is now %d", (int)EVBUFFER_LENGTH(out) );
}
static void
@ -413,12 +418,12 @@ protocolSendHave( tr_peermsgs * msgs, uint32_t index )
tr_peerIo * io = msgs->io;
struct evbuffer * out = msgs->outMessages;
dbgmsg( msgs, "sending Have %u", index );
tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + sizeof(uint32_t) );
tr_peerIoWriteUint8 ( io, out, BT_HAVE );
tr_peerIoWriteUint32( io, out, index );
dbgmsg( msgs, "sending Have %u.. outMessage size is now %d",
index, (int)EVBUFFER_LENGTH(out) );
pokeBatchPeriod( msgs, LOW_PRIORITY_INTERVAL_SECS );
dbgmsg( msgs, "outMessage size is now %d", (int)EVBUFFER_LENGTH(out) );
}
static void
@ -427,11 +432,12 @@ protocolSendChoke( tr_peermsgs * msgs, int choke )
tr_peerIo * io = msgs->io;
struct evbuffer * out = msgs->outMessages;
dbgmsg( msgs, "sending %s", (choke ? "Choke" : "Unchoke") );
tr_peerIoWriteUint32( io, out, sizeof(uint8_t) );
tr_peerIoWriteUint8 ( io, out, choke ? BT_CHOKE : BT_UNCHOKE );
dbgmsg( msgs, "sending %s... outMessage size is now %d",
(choke ? "Choke" : "Unchoke"),
(int)EVBUFFER_LENGTH(out) );
pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
dbgmsg( msgs, "outMessage size is now %d", (int)EVBUFFER_LENGTH(out) );
}
/**
@ -951,8 +957,8 @@ sendLtepHandshake( tr_peermsgs * msgs )
pex = 1;
tr_bencInitDict( &val, 4 );
tr_bencDictAddInt( &val, "e", msgs->handle->encryptionMode != TR_CLEAR_PREFERRED );
tr_bencDictAddInt( &val, "p", tr_sessionGetPeerPort( msgs->handle ) );
tr_bencDictAddInt( &val, "e", msgs->session->encryptionMode != TR_CLEAR_PREFERRED );
tr_bencDictAddInt( &val, "p", tr_sessionGetPeerPort( msgs->session ) );
tr_bencDictAddStr( &val, "v", TR_NAME " " USERAGENT_PREFIX );
m = tr_bencDictAddDict( &val, "m", 1 );
if( pex )
@ -1034,7 +1040,7 @@ parseUtPex( tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf )
tr_bencDictFindRaw( &val, "added.f", &added_f, &added_f_len );
pex = tr_peerMgrCompactToPex( added->val.s.s, added->val.s.i, added_f, added_f_len, &n );
for( i=0; i<n; ++i )
tr_peerMgrAddPex( msgs->handle->peerMgr, tor->info.hash,
tr_peerMgrAddPex( msgs->session->peerMgr, tor->info.hash,
TR_PEER_FROM_PEX, pex+i );
tr_free( pex );
}
@ -1750,15 +1756,42 @@ gotError( struct bufferevent * evbuf UNUSED, short what, void * vmsgs )
static void
sendBitfield( tr_peermsgs * msgs )
{
const tr_bitfield * bitfield = tr_cpPieceBitfield( msgs->torrent->completion );
struct evbuffer * out = msgs->outMessages;
const tr_piece_index_t pieceCount = msgs->torrent->info.pieceCount;
tr_bitfield * field;
tr_piece_index_t lazyPieces[LAZY_PIECE_COUNT];
int i;
int lazyCount = 0;
dbgmsg( msgs, "sending peer a bitfield message" );
tr_peerIoWriteUint32( msgs->io, out, sizeof(uint8_t) + bitfield->byteCount );
field = tr_bitfieldDup( tr_cpPieceBitfield( msgs->torrent->completion ) );
if( tr_sessionIsLazyBitfieldEnabled( msgs->session ) )
{
const int maxLazyCount = MIN( LAZY_PIECE_COUNT, pieceCount );
while( lazyCount < maxLazyCount )
{
const size_t pos = tr_cryptoRandInt ( pieceCount );
if( !tr_bitfieldHas( field, pos ) ) /* already removed it */
continue;
dbgmsg( msgs, "lazy bitfield #%d: piece %d of %d",
(int)(lazyCount+1), (int)pos, (int)pieceCount );
tr_bitfieldRem( field, pos );
lazyPieces[lazyCount++] = pos;
}
}
tr_peerIoWriteUint32( msgs->io, out, sizeof(uint8_t) + field->byteCount );
tr_peerIoWriteUint8 ( msgs->io, out, BT_BITFIELD );
tr_peerIoWriteBytes ( msgs->io, out, bitfield->bits, bitfield->byteCount );
tr_peerIoWriteBytes ( msgs->io, out, field->bits, field->byteCount );
dbgmsg( msgs, "sending bitfield... outMessage size is now %d",
(int)EVBUFFER_LENGTH(out) );
pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
dbgmsg( msgs, "outMessage size is now %d", (int)EVBUFFER_LENGTH(out) );
for( i=0; i<lazyCount; ++i )
protocolSendHave( msgs, lazyPieces[i] );
tr_bitfieldFree( field );
}
/**
@ -1820,7 +1853,7 @@ sendPex( tr_peermsgs * msgs )
{
int i;
tr_pex * newPex = NULL;
const int newCount = tr_peerMgrGetPeers( msgs->handle->peerMgr, msgs->torrent->info.hash, &newPex );
const int newCount = tr_peerMgrGetPeers( msgs->session->peerMgr, msgs->torrent->info.hash, &newPex );
PexDiffs diffs;
tr_benc val, *added, *dropped;
uint8_t *tmp, *walk;
@ -1923,7 +1956,7 @@ tr_peerMsgsNew( struct tr_torrent * torrent,
m = tr_new0( tr_peermsgs, 1 );
m->publisher = tr_publisherNew( );
m->info = info;
m->handle = torrent->handle;
m->session = torrent->handle;
m->torrent = torrent;
m->io = info->io;
m->info->clientIsChoked = 1;
@ -1932,9 +1965,9 @@ tr_peerMsgsNew( struct tr_torrent * torrent,
m->info->peerIsInterested = 0;
m->info->have = tr_bitfieldNew( torrent->info.pieceCount );
m->state = AWAITING_BT_LENGTH;
m->pulseTimer = tr_timerNew( m->handle, peerPulse, m, PEER_PULSE_INTERVAL );
m->rateTimer = tr_timerNew( m->handle, ratePulse, m, RATE_PULSE_INTERVAL );
m->pexTimer = tr_timerNew( m->handle, pexPulse, m, PEX_INTERVAL );
m->pulseTimer = tr_timerNew( m->session, peerPulse, m, PEER_PULSE_INTERVAL );
m->rateTimer = tr_timerNew( m->session, ratePulse, m, RATE_PULSE_INTERVAL );
m->pexTimer = tr_timerNew( m->session, pexPulse, m, PEX_INTERVAL );
m->outMessages = evbuffer_new( );
m->outMessagesBatchedAt = 0;
m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;

View File

@ -19,6 +19,7 @@
#include "transmission.h"
#include "natpmp.h"
#include "net.h"
#include "peer-io.h"
#include "peer-mgr.h"
#include "port-forwarding.h"
#include "torrent.h"
@ -130,6 +131,9 @@ incomingPeersPulse( tr_shared * s )
if( socket < 0 )
break;
tr_deepLog( __FILE__, __LINE__, NULL, "New INCOMING connection %d (%s)",
socket, tr_peerIoAddrStr( &addr, port ) );
tr_peerMgrAddIncoming( s->h->peerMgr, &addr, port, socket );
}
}

View File

@ -179,9 +179,10 @@ tr_sessionInitFull( const char * configDir,
int isPortForwardingEnabled,
int publicPort,
tr_encryption_mode encryptionMode,
int isUploadLimitEnabled,
int useLazyBitfield,
int useUploadLimit,
int uploadLimit,
int isDownloadLimitEnabled,
int useDownloadLimit,
int downloadLimit,
int globalPeerLimit,
int messageLevel,
@ -224,7 +225,7 @@ tr_sessionInitFull( const char * configDir,
h->proxy = tr_strdup( proxy );
h->proxyPort = proxyPort;
h->proxyType = proxyType;
h->isProxyAuthEnabled = proxyAuthIsEnabled ? 1 : 0;
h->isProxyAuthEnabled = proxyAuthIsEnabled != 0;
h->proxyUsername = tr_strdup( proxyUsername );
h->proxyPassword = tr_strdup( proxyPassword );
@ -241,15 +242,17 @@ tr_sessionInitFull( const char * configDir,
h->tag = tr_strdup( tag );
h->peerMgr = tr_peerMgrNew( h );
h->useLazyBitfield = useLazyBitfield != 0;
/* Initialize rate and file descripts controls */
h->upload = tr_rcInit();
tr_rcSetLimit( h->upload, uploadLimit );
h->useUploadLimit = isUploadLimitEnabled;
h->useUploadLimit = useUploadLimit;
h->download = tr_rcInit();
tr_rcSetLimit( h->download, downloadLimit );
h->useDownloadLimit = isDownloadLimitEnabled;
h->useDownloadLimit = useDownloadLimit;
tr_fdInit( globalPeerLimit );
h->shared = tr_sharedInit( h, isPortForwardingEnabled, publicPort );
@ -288,6 +291,7 @@ tr_sessionInit( const char * configDir,
TR_DEFAULT_PORT_FORWARDING_ENABLED,
-1, /* public port */
TR_ENCRYPTION_PREFERRED, /* encryption mode */
TR_DEFAULT_LAZY_BITFIELD_ENABLED,
FALSE, /* use upload speed limit? */
-1, /* upload speed limit */
FALSE, /* use download speed limit? */
@ -643,9 +647,9 @@ tr_sessionLoadTorrents ( tr_handle * h,
***/
void
tr_sessionSetPexEnabled( tr_handle * handle, int isPexEnabled )
tr_sessionSetPexEnabled( tr_handle * handle, int enabled )
{
handle->isPexEnabled = isPexEnabled ? 1 : 0;
handle->isPexEnabled = enabled ? 1 : 0;
}
int
@ -658,6 +662,22 @@ tr_sessionIsPexEnabled( const tr_handle * handle )
****
***/
void
tr_sessionSetLazyBitfieldEnabled( tr_handle * handle, int enabled )
{
handle->useLazyBitfield = enabled ? 1 : 0;
}
int
tr_sessionIsLazyBitfieldEnabled( const tr_handle * handle )
{
return handle->useLazyBitfield;
}
/***
****
***/
void
tr_sessionSetPortForwardingEnabled( tr_handle * h, int enable )
{

View File

@ -57,6 +57,7 @@ struct tr_handle
unsigned int isClosed : 1;
unsigned int useUploadLimit : 1;
unsigned int useDownloadLimit : 1;
unsigned int useLazyBitfield : 1;
tr_encryption_mode encryptionMode;

View File

@ -113,6 +113,8 @@ tr_proxy_type;
/** @see tr_sessionInitFull */
#define TR_DEFAULT_PORT_STR "51413"
/** @see tr_sessionInitFull */
#define TR_DEFAULT_LAZY_BITFIELD_ENABLED 0
/** @see tr_sessionInitFull */
#define TR_DEFAULT_GLOBAL_PEER_LIMIT 200
/** @see tr_sessionInitFull */
#define TR_DEFAULT_PEER_SOCKET_TOS 8
@ -253,9 +255,10 @@ tr_handle * tr_sessionInitFull( const char * configDir,
int isPortForwardingEnabled,
int publicPort,
tr_encryption_mode encryptionMode,
int isUploadLimitEnabled,
int useLazyBitfield,
int useUploadLimit,
int uploadLimit,
int isDownloadLimitEnabled,
int useDownloadLimit,
int downloadLimit,
int peerLimit,
int messageLevel,
@ -496,6 +499,10 @@ void tr_sessionSetPexEnabled( tr_session *, int isEnabled );
int tr_sessionIsPexEnabled( const tr_session * );
void tr_sessionSetLazyBitfieldEnabled( tr_handle * handle, int enabled );
int tr_sessionIsLazyBitfieldEnabled( const tr_handle * handle );
tr_encryption_mode tr_sessionGetEncryption( tr_session * );
void tr_sessionSetEncryption( tr_session *, tr_encryption_mode mode );

View File

@ -209,6 +209,7 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
[fDefaults boolForKey: @"NatTraversal"],
[fDefaults integerForKey: @"BindPort"],
TR_ENCRYPTION_PREFERRED, /* reset in prefs */
TR_DEFAULT_LAZY_BITFIELD_ENABLED,
NO, /* reset in prefs */
-1, /* reset in prefs */
NO, /* reset in prefs */