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 $
15 #include "transmission.h"
16 #include "completion.h"
25 tr_cpReset( tr_completion
* cp
)
28 cp
->sizeWhenDoneIsDirty
= true;
29 cp
->haveValidIsDirty
= true;
30 tr_bitfieldSetHasNone( &cp
->blockBitfield
);
34 tr_cpConstruct( tr_completion
* cp
, tr_torrent
* tor
)
37 tr_bitfieldConstruct( &cp
->blockBitfield
, tor
->blockCount
);
42 tr_cpBlockInit( tr_completion
* cp
, const tr_bitfield
* b
)
46 /* set blockBitfield */
47 tr_bitfieldSetFromBitfield( &cp
->blockBitfield
, b
);
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
);
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
;
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
);
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 );
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
);
93 tr_cpBlockAdd( cp
, i
);
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;
116 tr_cpHaveValid( const tr_completion
* ccp
)
118 if( ccp
->haveValidIsDirty
)
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
;
138 tr_cpSizeWhenDone( const tr_completion
* ccp
)
140 if( ccp
->sizeWhenDoneIsDirty
)
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
;
154 for( p
=0; p
<tor
->info
.pieceCount
; ++p
)
156 if( !tor
->info
.pieces
[p
].dnd
)
158 size
+= tr_torPieceCountBytes( tor
, p
);
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
;
179 tr_cpGetAmountDone( const tr_completion
* cp
, float * tab
, int tabCount
)
182 const bool seed
= tr_cpHasAll( cp
);
183 const float interval
= cp
->tor
->info
.pieceCount
/ (float)tabCount
;
185 for( i
=0; i
<tabCount
; ++i
) {
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 )
199 tr_cpMissingBlocksInPiece( const tr_completion
* cp
, tr_piece_index_t piece
)
201 if( tr_cpHasAll( cp
) )
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 );
211 tr_cpMissingBytesInPiece( const tr_completion
* cp
, tr_piece_index_t piece
)
213 if( tr_cpHasAll( cp
) )
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
);
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
;
235 tr_cpFileIsComplete( const tr_completion
* cp
, tr_file_index_t i
)
237 if( cp
->tor
->info
.files
[i
].length
== 0 )
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
);
247 tr_cpCreatePieceBitfield( const tr_completion
* cp
, size_t * byte_count
)
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
) ) {
259 if( tr_cpPieceIsComplete( cp
, i
) )
260 tr_bitfieldAdd( &pieces
, i
);
263 ret
= tr_bitfieldGetRaw( &pieces
, byte_count
);
264 tr_bitfieldDestruct( &pieces
);
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
)
275 else if( (int)ratio
== TR_RATIO_INF
)
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
;