Transmission 2.33
[tomato.git] / release / src / router / transmission / libtransmission / completion.c
bloba47e0e98217b10cd6f0016dcfd96f7d53cbc36f2
1 /*
2 * This file Copyright (C) Mnemosyne LLC
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
10 * $Id: completion.c 12531 2011-07-02 13:20:17Z jordan $
13 #include <assert.h>
15 #include "transmission.h"
16 #include "completion.h"
17 #include "torrent.h"
18 #include "utils.h"
20 /***
21 ****
22 ***/
24 static void
25 tr_cpReset( tr_completion * cp )
27 cp->sizeNow = 0;
28 cp->sizeWhenDoneIsDirty = true;
29 cp->haveValidIsDirty = true;
30 tr_bitfieldSetHasNone( &cp->blockBitfield );
33 void
34 tr_cpConstruct( tr_completion * cp, tr_torrent * tor )
36 cp->tor = tor;
37 tr_bitfieldConstruct( &cp->blockBitfield, tor->blockCount );
38 tr_cpReset( cp );
41 void
42 tr_cpBlockInit( tr_completion * cp, const tr_bitfield * b )
44 tr_cpReset( cp );
46 /* set blockBitfield */
47 tr_bitfieldSetFromBitfield( &cp->blockBitfield, b );
49 /* set sizeNow */
50 cp->sizeNow = tr_bitfieldCountTrueBits( &cp->blockBitfield );
51 cp->sizeNow *= cp->tor->blockSize;
52 if( tr_bitfieldHas( b, cp->tor->blockCount-1 ) )
53 cp->sizeNow -= ( cp->tor->blockSize - cp->tor->lastBlockSize );
56 /***
57 ****
58 ***/
60 tr_completeness
61 tr_cpGetStatus( const tr_completion * cp )
63 if( tr_cpHasAll( cp ) ) return TR_SEED;
64 if( !tr_torrentHasMetadata( cp->tor ) ) return TR_LEECH;
65 if( cp->sizeNow == tr_cpSizeWhenDone( cp ) ) return TR_PARTIAL_SEED;
66 return TR_LEECH;
69 void
70 tr_cpPieceRem( tr_completion * cp, tr_piece_index_t piece )
72 tr_block_index_t i, f, l;
73 const tr_torrent * tor = cp->tor;
75 tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
77 for( i=f; i<=l; ++i )
78 if( tr_cpBlockIsComplete( cp, i ) )
79 cp->sizeNow -= tr_torBlockCountBytes( tor, i );
81 cp->haveValidIsDirty = true;
82 cp->sizeWhenDoneIsDirty = true;
83 tr_bitfieldRemRange( &cp->blockBitfield, f, l+1 );
86 void
87 tr_cpPieceAdd( tr_completion * cp, tr_piece_index_t piece )
89 tr_block_index_t i, f, l;
90 tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
92 for( i=f; i<=l; ++i )
93 tr_cpBlockAdd( cp, i );
96 void
97 tr_cpBlockAdd( tr_completion * cp, tr_block_index_t block )
99 const tr_torrent * tor = cp->tor;
101 if( !tr_cpBlockIsComplete( cp, block ) )
103 tr_bitfieldAdd( &cp->blockBitfield, block );
104 cp->sizeNow += tr_torBlockCountBytes( tor, block );
106 cp->haveValidIsDirty = true;
107 cp->sizeWhenDoneIsDirty = true;
111 /***
112 ****
113 ***/
115 uint64_t
116 tr_cpHaveValid( const tr_completion * ccp )
118 if( ccp->haveValidIsDirty )
120 tr_piece_index_t i;
121 uint64_t size = 0;
122 tr_completion * cp = (tr_completion *) ccp; /* mutable */
123 const tr_torrent * tor = ccp->tor;
124 const tr_info * info = &tor->info;
126 for( i=0; i<info->pieceCount; ++i )
127 if( tr_cpPieceIsComplete( ccp, i ) )
128 size += tr_torPieceCountBytes( tor, i );
130 cp->haveValidLazy = size;
131 cp->haveValidIsDirty = false;
134 return ccp->haveValidLazy;
137 uint64_t
138 tr_cpSizeWhenDone( const tr_completion * ccp )
140 if( ccp->sizeWhenDoneIsDirty )
142 uint64_t size = 0;
143 const tr_torrent * tor = ccp->tor;
144 tr_completion * cp = (tr_completion *) ccp; /* mutable */
146 if( tr_cpHasAll( ccp ) )
148 size = tor->info.totalSize;
150 else
152 tr_piece_index_t p;
154 for( p=0; p<tor->info.pieceCount; ++p )
156 if( !tor->info.pieces[p].dnd )
158 size += tr_torPieceCountBytes( tor, p );
160 else
162 tr_block_index_t b, f, l;
163 tr_torGetPieceBlockRange( cp->tor, p, &f, &l );
164 for( b=f; b<=l; ++b )
165 if( tr_cpBlockIsComplete( cp, b ) )
166 size += tr_torBlockCountBytes( tor, b );
171 cp->sizeWhenDoneLazy = size;
172 cp->sizeWhenDoneIsDirty = false;
175 return ccp->sizeWhenDoneLazy;
178 void
179 tr_cpGetAmountDone( const tr_completion * cp, float * tab, int tabCount )
181 int i;
182 const bool seed = tr_cpHasAll( cp );
183 const float interval = cp->tor->info.pieceCount / (float)tabCount;
185 for( i=0; i<tabCount; ++i ) {
186 if( seed )
187 tab[i] = 1.0f;
188 else {
189 tr_block_index_t f, l;
190 const tr_piece_index_t piece = (tr_piece_index_t)i * interval;
191 tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
192 tab[i] = tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 )
193 / (float)(l+1-f);
198 size_t
199 tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece )
201 if( tr_cpHasAll( cp ) )
202 return 0;
203 else {
204 tr_block_index_t f, l;
205 tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
206 return (l+1-f) - tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 );
210 size_t
211 tr_cpMissingBytesInPiece( const tr_completion * cp, tr_piece_index_t piece )
213 if( tr_cpHasAll( cp ) )
214 return 0;
215 else {
216 size_t haveBytes = 0;
217 tr_block_index_t f, l;
218 const size_t pieceByteSize = tr_torPieceCountBytes( cp->tor, piece );
219 tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
220 if( f != l ) {
221 /* nb: we don't pass the usual l+1 here to tr_bitfieldCountRange().
222 It's faster to handle the last block separately because its size
223 needs to be checked separately. */
224 haveBytes = tr_bitfieldCountRange( &cp->blockBitfield, f, l );
225 haveBytes *= cp->tor->blockSize;
227 if( tr_bitfieldHas( &cp->blockBitfield, l ) ) /* handle the last block */
228 haveBytes += tr_torBlockCountBytes( cp->tor, l );
229 assert( haveBytes <= pieceByteSize );
230 return pieceByteSize - haveBytes;
234 bool
235 tr_cpFileIsComplete( const tr_completion * cp, tr_file_index_t i )
237 if( cp->tor->info.files[i].length == 0 )
238 return true;
239 else {
240 tr_block_index_t f, l;
241 tr_torGetFileBlockRange( cp->tor, i, &f, &l );
242 return tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 ) == (l+1-f);
246 void *
247 tr_cpCreatePieceBitfield( const tr_completion * cp, size_t * byte_count )
249 void * ret;
250 tr_bitfield pieces;
251 const tr_piece_index_t n = cp->tor->info.pieceCount;
252 tr_bitfieldConstruct( &pieces, n );
254 if( tr_cpHasAll( cp ) )
255 tr_bitfieldSetHasAll( &pieces );
256 else if( !tr_cpHasNone( cp ) ) {
257 tr_piece_index_t i;
258 for( i=0; i<n; ++i )
259 if( tr_cpPieceIsComplete( cp, i ) )
260 tr_bitfieldAdd( &pieces, i );
263 ret = tr_bitfieldGetRaw( &pieces, byte_count );
264 tr_bitfieldDestruct( &pieces );
265 return ret;
268 double
269 tr_cpPercentComplete( const tr_completion * cp )
271 const double ratio = tr_getRatio( cp->sizeNow, cp->tor->info.totalSize );
273 if( (int)ratio == TR_RATIO_NA )
274 return 0.0;
275 else if( (int)ratio == TR_RATIO_INF )
276 return 1.0;
277 else
278 return ratio;
281 double
282 tr_cpPercentDone( const tr_completion * cp )
284 const double ratio = tr_getRatio( cp->sizeNow, tr_cpSizeWhenDone( cp ) );
285 const int iratio = (int)ratio;
286 return ((iratio == TR_RATIO_NA) || (iratio == TR_RATIO_INF)) ? 0.0 : ratio;